Extract out FileTypes namespace

This commit is contained in:
Matt Nadareski
2020-12-08 14:53:49 -08:00
parent 0512e393c8
commit 82e3a3939b
134 changed files with 500 additions and 641 deletions

View File

@@ -10,12 +10,11 @@ using System.Threading.Tasks;
using System.Xml.Serialization;
using SabreTools.Core;
using SabreTools.FileTypes;
using SabreTools.Filtering;
using SabreTools.IO;
using SabreTools.Logging;
using SabreTools.Library.DatItems;
using SabreTools.Library.FileTypes;
using SabreTools.Library.IO;
using SabreTools.Library.Reports;
using SabreTools.Skippers;
using NaturalSort;
@@ -2556,7 +2555,7 @@ namespace SabreTools.Library.DatFiles
outputFormat = Header.ForcePacking.AsOutputFormat();
// Preload the Skipper list
Transform.Init();
SkipperMatch.Init();
#endregion
@@ -2696,7 +2695,7 @@ namespace SabreTools.Library.DatFiles
outputFormat = Header.ForcePacking.AsOutputFormat();
// Preload the Skipper list
Transform.Init();
SkipperMatch.Init();
#endregion
@@ -2908,7 +2907,7 @@ namespace SabreTools.Library.DatFiles
if (Header.HeaderSkipper != null)
{
// Check to see if we have a matching header first
SkipperRule rule = Transform.GetMatchingRule(fileStream, Path.GetFileNameWithoutExtension(Header.HeaderSkipper));
SkipperRule rule = SkipperMatch.GetMatchingRule(fileStream, Path.GetFileNameWithoutExtension(Header.HeaderSkipper));
// If there's a match, create the new file to write
if (rule.Tests != null && rule.Tests.Count != 0)

View File

@@ -5,9 +5,9 @@ using System.Linq;
using System.Xml.Serialization;
using SabreTools.Core;
using SabreTools.FileTypes;
using SabreTools.Filtering;
using SabreTools.Logging;
using SabreTools.Library.FileTypes;
using NaturalSort;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

View File

@@ -4,8 +4,8 @@ using System.Linq;
using System.Xml.Serialization;
using SabreTools.Core;
using SabreTools.FileTypes;
using SabreTools.Filtering;
using SabreTools.Library.FileTypes;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

View File

@@ -5,8 +5,8 @@ using System.Text;
using System.Xml.Serialization;
using SabreTools.Core;
using SabreTools.FileTypes;
using SabreTools.Filtering;
using SabreTools.Library.FileTypes;
using Newtonsoft.Json;
namespace SabreTools.Library.DatItems

View File

@@ -6,8 +6,8 @@ using System.Text;
using System.Xml.Serialization;
using SabreTools.Core;
using SabreTools.FileTypes;
using SabreTools.Filtering;
using SabreTools.Library.FileTypes;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

View File

@@ -1,214 +0,0 @@
using System;
using System.IO;
using Compress.Utils;
using Path = RVIO.Path;
using FileInfo = RVIO.FileInfo;
using FileStream = RVIO.FileStream;
namespace Compress.File
{
public class File : ICompress
{
private FileInfo _fileInfo;
private Stream _inStream;
private byte[] _crc;
public string ZipFilename => _fileInfo?.FullName ?? string.Empty;
public long TimeStamp => _fileInfo?.LastWriteTime ?? 0;
public ZipOpenType ZipOpen { get; private set; }
public ZipStatus ZipStatus { get; private set; }
public int LocalFilesCount()
{
return 1;
}
public string Filename(int i)
{
return Path.GetFileName(ZipFilename);
}
public bool IsDirectory(int i)
{
return RVIO.Directory.Exists(ZipFilename);
}
public ulong UncompressedSize(int i)
{
return _fileInfo != null ? (ulong)_fileInfo.Length : 0;
}
public ulong? LocalHeader(int i)
{
return 0;
}
public ZipReturn FileStatus(int i)
{
return ZipReturn.ZipGood;
}
public byte[] CRC32(int i)
{
return _crc;
}
public ZipReturn ZipFileCreate(string newFilename)
{
if (ZipOpen != ZipOpenType.Closed)
{
return ZipReturn.ZipFileAlreadyOpen;
}
DirUtil.CreateDirForFile(newFilename);
_fileInfo = new FileInfo(newFilename);
int errorCode = FileStream.OpenFileWrite(newFilename, out _inStream);
if (errorCode != 0)
{
ZipFileClose();
return ZipReturn.ZipErrorOpeningFile;
}
ZipOpen = ZipOpenType.OpenWrite;
return ZipReturn.ZipGood;
}
public void ZipFileClose()
{
if (ZipOpen == ZipOpenType.Closed)
{
return;
}
if (ZipOpen == ZipOpenType.OpenRead)
{
if (_inStream != null)
{
_inStream.Close();
_inStream.Dispose();
}
ZipOpen = ZipOpenType.Closed;
return;
}
_inStream.Flush();
_inStream.Close();
_inStream.Dispose();
_fileInfo = new FileInfo(_fileInfo.FullName);
ZipOpen = ZipOpenType.Closed;
}
public ZipReturn ZipFileOpen(string newFilename, long timestamp, bool readHeaders)
{
ZipFileClose();
ZipStatus = ZipStatus.None;
_fileInfo = null;
try
{
if (!RVIO.File.Exists(newFilename))
{
ZipFileClose();
return ZipReturn.ZipErrorFileNotFound;
}
_fileInfo = new FileInfo(newFilename);
if (timestamp != -1 && _fileInfo.LastWriteTime != timestamp)
{
ZipFileClose();
return ZipReturn.ZipErrorTimeStamp;
}
int errorCode = FileStream.OpenFileRead(newFilename, out _inStream);
if (errorCode != 0)
{
ZipFileClose();
if (errorCode == 32)
{
return ZipReturn.ZipFileLocked;
}
return ZipReturn.ZipErrorOpeningFile;
}
}
catch (PathTooLongException)
{
ZipFileClose();
return ZipReturn.ZipFileNameToLong;
}
catch (IOException)
{
ZipFileClose();
return ZipReturn.ZipErrorOpeningFile;
}
ZipOpen = ZipOpenType.OpenRead;
if (!readHeaders)
{
return ZipReturn.ZipGood;
}
//return ZipFileReadHeaders();
return ZipReturn.ZipGood;
}
public ZipReturn ZipFileOpen(Stream inStream)
{
ZipFileClose();
ZipStatus = ZipStatus.None;
_fileInfo = null;
_inStream = inStream;
ZipOpen = ZipOpenType.OpenRead;
//return ZipFileReadHeaders();
return ZipReturn.ZipGood;
}
public void ZipFileAddZeroLengthFile()
{
throw new NotImplementedException();
}
public ZipReturn ZipFileCloseWriteStream(byte[] crc32)
{
_crc = crc32;
return ZipReturn.ZipGood;
}
public void ZipFileCloseFailed()
{
throw new NotImplementedException();
}
public ZipReturn ZipFileOpenReadStream(int index, out Stream stream, out ulong streamSize)
{
_inStream.Position = 0;
stream = _inStream;
streamSize = (ulong)_fileInfo.Length;
return ZipReturn.ZipGood;
}
public ZipReturn ZipFileOpenWriteStream(bool raw, bool trrntzip, string filename, ulong uncompressedSize, ushort compressionMethod, uint? datetime, out Stream stream)
{
_inStream.Position = 0;
stream = _inStream;
return ZipReturn.ZipGood;
}
public ZipReturn ZipFileCloseReadStream()
{
return ZipReturn.ZipGood;
}
}
}

View File

@@ -1,40 +0,0 @@
using System.IO;
namespace Compress
{
public interface ICompress
{
int LocalFilesCount();
string Filename(int i);
ulong? LocalHeader(int i);
ulong UncompressedSize(int i);
byte[] CRC32(int i);
bool IsDirectory(int i);
ZipOpenType ZipOpen { get; }
ZipReturn ZipFileOpen(string newFilename, long timestamp = -1, bool readHeaders = true);
ZipReturn ZipFileOpen(Stream inStream);
void ZipFileClose();
ZipReturn ZipFileOpenReadStream(int index, out Stream stream, out ulong streamSize);
ZipReturn ZipFileOpenWriteStream(bool raw, bool trrntzip, string filename, ulong uncompressedSize, ushort compressionMethod, uint? datetime, out Stream stream);
ZipReturn ZipFileCloseReadStream();
ZipStatus ZipStatus { get; }
string ZipFilename { get; }
long TimeStamp { get; }
void ZipFileAddZeroLengthFile();
ZipReturn ZipFileCreate(string newFilename);
ZipReturn ZipFileCloseWriteStream(byte[] crc32);
void ZipFileCloseFailed();
}
}

View File

@@ -1,152 +0,0 @@
using System;
namespace Compress.SevenZip.Common
{
/// <summary>
/// The exception that is thrown when an error in input stream occurs during decoding.
/// </summary>
public class DataErrorException : Exception
{
public DataErrorException() : base("Data Error") { }
}
/// <summary>
/// The exception that is thrown when the value of an argument is outside the allowable range.
/// </summary>
internal class InvalidParamException : Exception
{
public InvalidParamException() : base("Invalid Parameter") { }
}
public interface ICodeProgress
{
/// <summary>
/// Callback progress.
/// </summary>
/// <param name="inSize">
/// input size. -1 if unknown.
/// </param>
/// <param name="outSize">
/// output size. -1 if unknown.
/// </param>
void SetProgress(Int64 inSize, Int64 outSize);
};
internal interface ICoder
{
/// <summary>
/// Codes streams.
/// </summary>
/// <param name="inStream">
/// input Stream.
/// </param>
/// <param name="outStream">
/// output Stream.
/// </param>
/// <param name="inSize">
/// input Size. -1 if unknown.
/// </param>
/// <param name="outSize">
/// output Size. -1 if unknown.
/// </param>
/// <param name="progress">
/// callback progress reference.
/// </param>
void Code(System.IO.Stream inStream, System.IO.Stream outStream,
Int64 inSize, Int64 outSize, ICodeProgress progress);
};
/*
public interface ICoder2
{
void Code(ISequentialInStream []inStreams,
const UInt64 []inSizes,
ISequentialOutStream []outStreams,
UInt64 []outSizes,
ICodeProgress progress);
};
*/
/// <summary>
/// Provides the fields that represent properties idenitifiers for compressing.
/// </summary>
internal enum CoderPropID
{
/// <summary>
/// Specifies default property.
/// </summary>
DefaultProp = 0,
/// <summary>
/// Specifies size of dictionary.
/// </summary>
DictionarySize,
/// <summary>
/// Specifies size of memory for PPM*.
/// </summary>
UsedMemorySize,
/// <summary>
/// Specifies order for PPM methods.
/// </summary>
Order,
/// <summary>
/// Specifies Block Size.
/// </summary>
BlockSize,
/// <summary>
/// Specifies number of postion state bits for LZMA (0 - x - 4).
/// </summary>
PosStateBits,
/// <summary>
/// Specifies number of literal context bits for LZMA (0 - x - 8).
/// </summary>
LitContextBits,
/// <summary>
/// Specifies number of literal position bits for LZMA (0 - x - 4).
/// </summary>
LitPosBits,
/// <summary>
/// Specifies number of fast bytes for LZ*.
/// </summary>
NumFastBytes,
/// <summary>
/// Specifies match finder. LZMA: "BT2", "BT4" or "BT4B".
/// </summary>
MatchFinder,
/// <summary>
/// Specifies the number of match finder cyckes.
/// </summary>
MatchFinderCycles,
/// <summary>
/// Specifies number of passes.
/// </summary>
NumPasses,
/// <summary>
/// Specifies number of algorithm.
/// </summary>
Algorithm,
/// <summary>
/// Specifies the number of threads.
/// </summary>
NumThreads,
/// <summary>
/// Specifies mode with end marker.
/// </summary>
EndMarker
};
internal interface ISetCoderProperties
{
void SetCoderProperties(CoderPropID[] propIDs, object[] properties);
};
internal interface IWriteCoderProperties
{
void WriteCoderProperties(System.IO.Stream outStream);
}
internal interface ISetDecoderProperties
{
void SetDecoderProperties(byte[] properties);
}
}

View File

@@ -1,100 +0,0 @@
/*
* Copyright 2001,2004-2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* This package is based on the work done by Keiron Liddle, Aftex Software
* <keiron@aftexsw.com> to whom the Ant project is very grateful for his
* great code.
*/
namespace Compress.SevenZip.Compress.BZip2
{
/**
* Base class for both the compress and decompress classes.
* Holds common arrays, and static data.
*
* @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a>
*/
internal class BZip2Constants
{
public const int baseBlockSize = 100000;
public const int MAX_ALPHA_SIZE = 258;
public const int MAX_CODE_LEN = 23;
public const int RUNA = 0;
public const int RUNB = 1;
public const int N_GROUPS = 6;
public const int G_SIZE = 50;
public const int N_ITERS = 4;
public const int MAX_SELECTORS = (2 + (900000 / G_SIZE));
public const int NUM_OVERSHOOT_BYTES = 20;
public static int[] rNums = {
619, 720, 127, 481, 931, 816, 813, 233, 566, 247,
985, 724, 205, 454, 863, 491, 741, 242, 949, 214,
733, 859, 335, 708, 621, 574, 73, 654, 730, 472,
419, 436, 278, 496, 867, 210, 399, 680, 480, 51,
878, 465, 811, 169, 869, 675, 611, 697, 867, 561,
862, 687, 507, 283, 482, 129, 807, 591, 733, 623,
150, 238, 59, 379, 684, 877, 625, 169, 643, 105,
170, 607, 520, 932, 727, 476, 693, 425, 174, 647,
73, 122, 335, 530, 442, 853, 695, 249, 445, 515,
909, 545, 703, 919, 874, 474, 882, 500, 594, 612,
641, 801, 220, 162, 819, 984, 589, 513, 495, 799,
161, 604, 958, 533, 221, 400, 386, 867, 600, 782,
382, 596, 414, 171, 516, 375, 682, 485, 911, 276,
98, 553, 163, 354, 666, 933, 424, 341, 533, 870,
227, 730, 475, 186, 263, 647, 537, 686, 600, 224,
469, 68, 770, 919, 190, 373, 294, 822, 808, 206,
184, 943, 795, 384, 383, 461, 404, 758, 839, 887,
715, 67, 618, 276, 204, 918, 873, 777, 604, 560,
951, 160, 578, 722, 79, 804, 96, 409, 713, 940,
652, 934, 970, 447, 318, 353, 859, 672, 112, 785,
645, 863, 803, 350, 139, 93, 354, 99, 820, 908,
609, 772, 154, 274, 580, 184, 79, 626, 630, 742,
653, 282, 762, 623, 680, 81, 927, 626, 789, 125,
411, 521, 938, 300, 821, 78, 343, 175, 128, 250,
170, 774, 972, 275, 999, 639, 495, 78, 352, 126,
857, 956, 358, 619, 580, 124, 737, 594, 701, 612,
669, 112, 134, 694, 363, 992, 809, 743, 168, 974,
944, 375, 748, 52, 600, 747, 642, 182, 862, 81,
344, 805, 988, 739, 511, 655, 814, 334, 249, 515,
897, 955, 664, 981, 649, 113, 974, 459, 893, 228,
433, 837, 553, 268, 926, 240, 102, 654, 459, 51,
686, 754, 806, 760, 493, 403, 415, 394, 687, 700,
946, 670, 656, 610, 738, 392, 760, 799, 887, 653,
978, 321, 576, 617, 626, 502, 894, 679, 243, 440,
680, 879, 194, 572, 640, 724, 926, 56, 204, 700,
707, 151, 457, 449, 797, 195, 791, 558, 945, 679,
297, 59, 87, 824, 713, 663, 412, 693, 342, 606,
134, 108, 571, 364, 631, 212, 174, 643, 304, 329,
343, 97, 430, 751, 497, 314, 983, 374, 822, 928,
140, 206, 73, 263, 980, 736, 876, 478, 430, 305,
170, 514, 364, 692, 829, 82, 855, 953, 676, 246,
369, 970, 294, 750, 807, 827, 150, 790, 288, 923,
804, 378, 215, 828, 592, 281, 565, 555, 710, 82,
896, 831, 547, 261, 524, 462, 293, 465, 502, 56,
661, 821, 976, 991, 658, 869, 905, 758, 745, 193,
768, 550, 608, 933, 378, 286, 215, 979, 792, 961,
61, 688, 793, 644, 986, 403, 106, 366, 905, 644,
372, 567, 466, 434, 645, 210, 389, 550, 919, 135,
780, 773, 635, 389, 707, 100, 626, 958, 165, 504,
920, 176, 193, 713, 857, 265, 203, 50, 668, 108,
645, 990, 626, 197, 510, 357, 358, 850, 858, 364,
936, 638
};
}
}

View File

@@ -1,138 +0,0 @@

/*
* Copyright 2001,2004-2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* This package is based on the work done by Keiron Liddle), Aftex Software
* <keiron@aftexsw.com> to whom the Ant project is very grateful for his
* great code.
*/
namespace Compress.SevenZip.Compress.BZip2
{
/**
* A simple class the hold and calculate the CRC for sanity checking
* of the data.
*
* @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a>
*/
internal class CRC
{
private static readonly int[] crc32Table = {
unchecked((int)0x00000000), unchecked((int)0x04c11db7), unchecked((int)0x09823b6e), unchecked((int)0x0d4326d9),
unchecked((int)0x130476dc), unchecked((int)0x17c56b6b), unchecked((int)0x1a864db2), unchecked((int)0x1e475005),
unchecked((int)0x2608edb8), unchecked((int)0x22c9f00f), unchecked((int)0x2f8ad6d6), unchecked((int)0x2b4bcb61),
unchecked((int)0x350c9b64), unchecked((int)0x31cd86d3), unchecked((int)0x3c8ea00a), unchecked((int)0x384fbdbd),
unchecked((int)0x4c11db70), unchecked((int)0x48d0c6c7), unchecked((int)0x4593e01e), unchecked((int)0x4152fda9),
unchecked((int)0x5f15adac), unchecked((int)0x5bd4b01b), unchecked((int)0x569796c2), unchecked((int)0x52568b75),
unchecked((int)0x6a1936c8), unchecked((int)0x6ed82b7f), unchecked((int)0x639b0da6), unchecked((int)0x675a1011),
unchecked((int)0x791d4014), unchecked((int)0x7ddc5da3), unchecked((int)0x709f7b7a), unchecked((int)0x745e66cd),
unchecked((int)0x9823b6e0), unchecked((int)0x9ce2ab57), unchecked((int)0x91a18d8e), unchecked((int)0x95609039),
unchecked((int)0x8b27c03c), unchecked((int)0x8fe6dd8b), unchecked((int)0x82a5fb52), unchecked((int)0x8664e6e5),
unchecked((int)0xbe2b5b58), unchecked((int)0xbaea46ef), unchecked((int)0xb7a96036), unchecked((int)0xb3687d81),
unchecked((int)0xad2f2d84), unchecked((int)0xa9ee3033), unchecked((int)0xa4ad16ea), unchecked((int)0xa06c0b5d),
unchecked((int)0xd4326d90), unchecked((int)0xd0f37027), unchecked((int)0xddb056fe), unchecked((int)0xd9714b49),
unchecked((int)0xc7361b4c), unchecked((int)0xc3f706fb), unchecked((int)0xceb42022), unchecked((int)0xca753d95),
unchecked((int)0xf23a8028), unchecked((int)0xf6fb9d9f), unchecked((int)0xfbb8bb46), unchecked((int)0xff79a6f1),
unchecked((int)0xe13ef6f4), unchecked((int)0xe5ffeb43), unchecked((int)0xe8bccd9a), unchecked((int)0xec7dd02d),
unchecked((int)0x34867077), unchecked((int)0x30476dc0), unchecked((int)0x3d044b19), unchecked((int)0x39c556ae),
unchecked((int)0x278206ab), unchecked((int)0x23431b1c), unchecked((int)0x2e003dc5), unchecked((int)0x2ac12072),
unchecked((int)0x128e9dcf), unchecked((int)0x164f8078), unchecked((int)0x1b0ca6a1), unchecked((int)0x1fcdbb16),
unchecked((int)0x018aeb13), unchecked((int)0x054bf6a4), unchecked((int)0x0808d07d), unchecked((int)0x0cc9cdca),
unchecked((int)0x7897ab07), unchecked((int)0x7c56b6b0), unchecked((int)0x71159069), unchecked((int)0x75d48dde),
unchecked((int)0x6b93dddb), unchecked((int)0x6f52c06c), unchecked((int)0x6211e6b5), unchecked((int)0x66d0fb02),
unchecked((int)0x5e9f46bf), unchecked((int)0x5a5e5b08), unchecked((int)0x571d7dd1), unchecked((int)0x53dc6066),
unchecked((int)0x4d9b3063), unchecked((int)0x495a2dd4), unchecked((int)0x44190b0d), unchecked((int)0x40d816ba),
unchecked((int)0xaca5c697), unchecked((int)0xa864db20), unchecked((int)0xa527fdf9), unchecked((int)0xa1e6e04e),
unchecked((int)0xbfa1b04b), unchecked((int)0xbb60adfc), unchecked((int)0xb6238b25), unchecked((int)0xb2e29692),
unchecked((int)0x8aad2b2f), unchecked((int)0x8e6c3698), unchecked((int)0x832f1041), unchecked((int)0x87ee0df6),
unchecked((int)0x99a95df3), unchecked((int)0x9d684044), unchecked((int)0x902b669d), unchecked((int)0x94ea7b2a),
unchecked((int)0xe0b41de7), unchecked((int)0xe4750050), unchecked((int)0xe9362689), unchecked((int)0xedf73b3e),
unchecked((int)0xf3b06b3b), unchecked((int)0xf771768c), unchecked((int)0xfa325055), unchecked((int)0xfef34de2),
unchecked((int)0xc6bcf05f), unchecked((int)0xc27dede8), unchecked((int)0xcf3ecb31), unchecked((int)0xcbffd686),
unchecked((int)0xd5b88683), unchecked((int)0xd1799b34), unchecked((int)0xdc3abded), unchecked((int)0xd8fba05a),
unchecked((int)0x690ce0ee), unchecked((int)0x6dcdfd59), unchecked((int)0x608edb80), unchecked((int)0x644fc637),
unchecked((int)0x7a089632), unchecked((int)0x7ec98b85), unchecked((int)0x738aad5c), unchecked((int)0x774bb0eb),
unchecked((int)0x4f040d56), unchecked((int)0x4bc510e1), unchecked((int)0x46863638), unchecked((int)0x42472b8f),
unchecked((int)0x5c007b8a), unchecked((int)0x58c1663d), unchecked((int)0x558240e4), unchecked((int)0x51435d53),
unchecked((int)0x251d3b9e), unchecked((int)0x21dc2629), unchecked((int)0x2c9f00f0), unchecked((int)0x285e1d47),
unchecked((int)0x36194d42), unchecked((int)0x32d850f5), unchecked((int)0x3f9b762c), unchecked((int)0x3b5a6b9b),
unchecked((int)0x0315d626), unchecked((int)0x07d4cb91), unchecked((int)0x0a97ed48), unchecked((int)0x0e56f0ff),
unchecked((int)0x1011a0fa), unchecked((int)0x14d0bd4d), unchecked((int)0x19939b94), unchecked((int)0x1d528623),
unchecked((int)0xf12f560e), unchecked((int)0xf5ee4bb9), unchecked((int)0xf8ad6d60), unchecked((int)0xfc6c70d7),
unchecked((int)0xe22b20d2), unchecked((int)0xe6ea3d65), unchecked((int)0xeba91bbc), unchecked((int)0xef68060b),
unchecked((int)0xd727bbb6), unchecked((int)0xd3e6a601), unchecked((int)0xdea580d8), unchecked((int)0xda649d6f),
unchecked((int)0xc423cd6a), unchecked((int)0xc0e2d0dd), unchecked((int)0xcda1f604), unchecked((int)0xc960ebb3),
unchecked((int)0xbd3e8d7e), unchecked((int)0xb9ff90c9), unchecked((int)0xb4bcb610), unchecked((int)0xb07daba7),
unchecked((int)0xae3afba2), unchecked((int)0xaafbe615), unchecked((int)0xa7b8c0cc), unchecked((int)0xa379dd7b),
unchecked((int)0x9b3660c6), unchecked((int)0x9ff77d71), unchecked((int)0x92b45ba8), unchecked((int)0x9675461f),
unchecked((int)0x8832161a), unchecked((int)0x8cf30bad), unchecked((int)0x81b02d74), unchecked((int)0x857130c3),
unchecked((int)0x5d8a9099), unchecked((int)0x594b8d2e), unchecked((int)0x5408abf7), unchecked((int)0x50c9b640),
unchecked((int)0x4e8ee645), unchecked((int)0x4a4ffbf2), unchecked((int)0x470cdd2b), unchecked((int)0x43cdc09c),
unchecked((int)0x7b827d21), unchecked((int)0x7f436096), unchecked((int)0x7200464f), unchecked((int)0x76c15bf8),
unchecked((int)0x68860bfd), unchecked((int)0x6c47164a), unchecked((int)0x61043093), unchecked((int)0x65c52d24),
unchecked((int)0x119b4be9), unchecked((int)0x155a565e), unchecked((int)0x18197087), unchecked((int)0x1cd86d30),
unchecked((int)0x029f3d35), unchecked((int)0x065e2082), unchecked((int)0x0b1d065b), unchecked((int)0x0fdc1bec),
unchecked((int)0x3793a651), unchecked((int)0x3352bbe6), unchecked((int)0x3e119d3f), unchecked((int)0x3ad08088),
unchecked((int)0x2497d08d), unchecked((int)0x2056cd3a), unchecked((int)0x2d15ebe3), unchecked((int)0x29d4f654),
unchecked((int)0xc5a92679), unchecked((int)0xc1683bce), unchecked((int)0xcc2b1d17), unchecked((int)0xc8ea00a0),
unchecked((int)0xd6ad50a5), unchecked((int)0xd26c4d12), unchecked((int)0xdf2f6bcb), unchecked((int)0xdbee767c),
unchecked((int)0xe3a1cbc1), unchecked((int)0xe760d676), unchecked((int)0xea23f0af), unchecked((int)0xeee2ed18),
unchecked((int)0xf0a5bd1d), unchecked((int)0xf464a0aa), unchecked((int)0xf9278673), unchecked((int)0xfde69bc4),
unchecked((int)0x89b8fd09), unchecked((int)0x8d79e0be), unchecked((int)0x803ac667), unchecked((int)0x84fbdbd0),
unchecked((int)0x9abc8bd5), unchecked((int)0x9e7d9662), unchecked((int)0x933eb0bb), unchecked((int)0x97ffad0c),
unchecked((int)0xafb010b1), unchecked((int)0xab710d06), unchecked((int)0xa6322bdf), unchecked((int)0xa2f33668),
unchecked((int)0xbcb4666d), unchecked((int)0xb8757bda), unchecked((int)0xb5365d03), unchecked((int)0xb1f740b4)
};
public CRC()
{
InitialiseCRC();
}
internal void InitialiseCRC()
{
globalCrc = unchecked((int)0xffffffff);
}
internal int GetFinalCRC()
{
return ~globalCrc;
}
internal int GetGlobalCRC()
{
return globalCrc;
}
internal void SetGlobalCRC(int newCrc)
{
globalCrc = newCrc;
}
internal void UpdateCRC(int inCh)
{
int temp = (globalCrc >> 24) ^ inCh;
if (temp < 0)
{
temp = 256 + temp;
}
globalCrc = (globalCrc << 8) ^ CRC.crc32Table[temp];
}
internal int globalCrc;
}
}

View File

@@ -1,366 +0,0 @@
using System;
using Compress.SevenZip.Common;
namespace Compress.SevenZip.Compress.LZ
{
internal class BinTree : InWindow
{
UInt32 _cyclicBufferPos;
UInt32 _cyclicBufferSize = 0;
UInt32 _matchMaxLen;
UInt32[] _son;
UInt32[] _hash;
UInt32 _cutValue = 0xFF;
UInt32 _hashMask;
UInt32 _hashSizeSum = 0;
bool HASH_ARRAY = true;
const UInt32 kHash2Size = 1 << 10;
const UInt32 kHash3Size = 1 << 16;
const UInt32 kBT2HashSize = 1 << 16;
const UInt32 kStartMaxLen = 1;
const UInt32 kHash3Offset = kHash2Size;
const UInt32 kEmptyHashValue = 0;
const UInt32 kMaxValForNormalize = ((UInt32)1 << 31) - 1;
UInt32 kNumHashDirectBytes = 0;
UInt32 kMinMatchCheck = 4;
UInt32 kFixHashSize = kHash2Size + kHash3Size;
public void SetType(int numHashBytes)
{
HASH_ARRAY = (numHashBytes > 2);
if (HASH_ARRAY)
{
kNumHashDirectBytes = 0;
kMinMatchCheck = 4;
kFixHashSize = kHash2Size + kHash3Size;
}
else
{
kNumHashDirectBytes = 2;
kMinMatchCheck = 2 + 1;
kFixHashSize = 0;
}
}
public new void SetStream(System.IO.Stream stream) { base.SetStream(stream); }
public new void ReleaseStream() { base.ReleaseStream(); }
public new void Init()
{
base.Init();
for (UInt32 i = 0; i < _hashSizeSum; i++)
_hash[i] = kEmptyHashValue;
_cyclicBufferPos = 0;
ReduceOffsets(-1);
}
public new void MovePos()
{
if (++_cyclicBufferPos >= _cyclicBufferSize)
_cyclicBufferPos = 0;
base.MovePos();
if (_pos == kMaxValForNormalize)
Normalize();
}
public new Byte GetIndexByte(Int32 index) { return base.GetIndexByte(index); }
public new UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit)
{ return base.GetMatchLen(index, distance, limit); }
public new UInt32 GetNumAvailableBytes() { return base.GetNumAvailableBytes(); }
public void Create(UInt32 historySize, UInt32 keepAddBufferBefore,
UInt32 matchMaxLen, UInt32 keepAddBufferAfter)
{
if (historySize > kMaxValForNormalize - 256)
throw new Exception();
_cutValue = 16 + (matchMaxLen >> 1);
UInt32 windowReservSize = (historySize + keepAddBufferBefore +
matchMaxLen + keepAddBufferAfter) / 2 + 256;
base.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize);
_matchMaxLen = matchMaxLen;
UInt32 cyclicBufferSize = historySize + 1;
if (_cyclicBufferSize != cyclicBufferSize)
_son = new UInt32[(_cyclicBufferSize = cyclicBufferSize) * 2];
UInt32 hs = kBT2HashSize;
if (HASH_ARRAY)
{
hs = historySize - 1;
hs |= (hs >> 1);
hs |= (hs >> 2);
hs |= (hs >> 4);
hs |= (hs >> 8);
hs >>= 1;
hs |= 0xFFFF;
if (hs > (1 << 24))
hs >>= 1;
_hashMask = hs;
hs++;
hs += kFixHashSize;
}
if (hs != _hashSizeSum)
_hash = new UInt32[_hashSizeSum = hs];
}
public UInt32 GetMatches(UInt32[] distances)
{
UInt32 lenLimit;
if (_pos + _matchMaxLen <= _streamPos)
lenLimit = _matchMaxLen;
else
{
lenLimit = _streamPos - _pos;
if (lenLimit < kMinMatchCheck)
{
MovePos();
return 0;
}
}
UInt32 offset = 0;
UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
UInt32 cur = _bufferOffset + _pos;
UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize;
UInt32 hashValue, hash2Value = 0, hash3Value = 0;
if (HASH_ARRAY)
{
UInt32 temp = Utils.CRC.CRC32Lookup[_bufferBase[cur]] ^ _bufferBase[cur + 1];
hash2Value = temp & (kHash2Size - 1);
temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8);
hash3Value = temp & (kHash3Size - 1);
hashValue = (temp ^ (Utils.CRC.CRC32Lookup[_bufferBase[cur + 3]] << 5)) & _hashMask;
}
else
hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8);
UInt32 curMatch = _hash[kFixHashSize + hashValue];
if (HASH_ARRAY)
{
UInt32 curMatch2 = _hash[hash2Value];
UInt32 curMatch3 = _hash[kHash3Offset + hash3Value];
_hash[hash2Value] = _pos;
_hash[kHash3Offset + hash3Value] = _pos;
if (curMatch2 > matchMinPos)
if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur])
{
distances[offset++] = maxLen = 2;
distances[offset++] = _pos - curMatch2 - 1;
}
if (curMatch3 > matchMinPos)
if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur])
{
if (curMatch3 == curMatch2)
offset -= 2;
distances[offset++] = maxLen = 3;
distances[offset++] = _pos - curMatch3 - 1;
curMatch2 = curMatch3;
}
if (offset != 0 && curMatch2 == curMatch)
{
offset -= 2;
maxLen = kStartMaxLen;
}
}
_hash[kFixHashSize + hashValue] = _pos;
UInt32 ptr0 = (_cyclicBufferPos << 1) + 1;
UInt32 ptr1 = (_cyclicBufferPos << 1);
UInt32 len0, len1;
len0 = len1 = kNumHashDirectBytes;
if (kNumHashDirectBytes != 0)
{
if (curMatch > matchMinPos)
{
if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] !=
_bufferBase[cur + kNumHashDirectBytes])
{
distances[offset++] = maxLen = kNumHashDirectBytes;
distances[offset++] = _pos - curMatch - 1;
}
}
}
UInt32 count = _cutValue;
while (true)
{
if (curMatch <= matchMinPos || count-- == 0)
{
_son[ptr0] = _son[ptr1] = kEmptyHashValue;
break;
}
UInt32 delta = _pos - curMatch;
UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ?
(_cyclicBufferPos - delta) :
(_cyclicBufferPos - delta + _cyclicBufferSize)) << 1;
UInt32 pby1 = _bufferOffset + curMatch;
UInt32 len = Math.Min(len0, len1);
if (_bufferBase[pby1 + len] == _bufferBase[cur + len])
{
while (++len != lenLimit)
if (_bufferBase[pby1 + len] != _bufferBase[cur + len])
break;
if (maxLen < len)
{
distances[offset++] = maxLen = len;
distances[offset++] = delta - 1;
if (len == lenLimit)
{
_son[ptr1] = _son[cyclicPos];
_son[ptr0] = _son[cyclicPos + 1];
break;
}
}
}
if (_bufferBase[pby1 + len] < _bufferBase[cur + len])
{
_son[ptr1] = curMatch;
ptr1 = cyclicPos + 1;
curMatch = _son[ptr1];
len1 = len;
}
else
{
_son[ptr0] = curMatch;
ptr0 = cyclicPos;
curMatch = _son[ptr0];
len0 = len;
}
}
MovePos();
return offset;
}
public void Skip(UInt32 num)
{
do
{
UInt32 lenLimit;
if (_pos + _matchMaxLen <= _streamPos)
lenLimit = _matchMaxLen;
else
{
lenLimit = _streamPos - _pos;
if (lenLimit < kMinMatchCheck)
{
MovePos();
continue;
}
}
UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
UInt32 cur = _bufferOffset + _pos;
UInt32 hashValue;
if (HASH_ARRAY)
{
UInt32 temp = Utils.CRC.CRC32Lookup[_bufferBase[cur]] ^ _bufferBase[cur + 1];
UInt32 hash2Value = temp & (kHash2Size - 1);
_hash[hash2Value] = _pos;
temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8);
UInt32 hash3Value = temp & (kHash3Size - 1);
_hash[kHash3Offset + hash3Value] = _pos;
hashValue = (temp ^ (Utils.CRC.CRC32Lookup[_bufferBase[cur + 3]] << 5)) & _hashMask;
}
else
hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8);
UInt32 curMatch = _hash[kFixHashSize + hashValue];
_hash[kFixHashSize + hashValue] = _pos;
UInt32 ptr0 = (_cyclicBufferPos << 1) + 1;
UInt32 ptr1 = (_cyclicBufferPos << 1);
UInt32 len0, len1;
len0 = len1 = kNumHashDirectBytes;
UInt32 count = _cutValue;
while (true)
{
if (curMatch <= matchMinPos || count-- == 0)
{
_son[ptr0] = _son[ptr1] = kEmptyHashValue;
break;
}
UInt32 delta = _pos - curMatch;
UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ?
(_cyclicBufferPos - delta) :
(_cyclicBufferPos - delta + _cyclicBufferSize)) << 1;
UInt32 pby1 = _bufferOffset + curMatch;
UInt32 len = Math.Min(len0, len1);
if (_bufferBase[pby1 + len] == _bufferBase[cur + len])
{
while (++len != lenLimit)
if (_bufferBase[pby1 + len] != _bufferBase[cur + len])
break;
if (len == lenLimit)
{
_son[ptr1] = _son[cyclicPos];
_son[ptr0] = _son[cyclicPos + 1];
break;
}
}
if (_bufferBase[pby1 + len] < _bufferBase[cur + len])
{
_son[ptr1] = curMatch;
ptr1 = cyclicPos + 1;
curMatch = _son[ptr1];
len1 = len;
}
else
{
_son[ptr0] = curMatch;
ptr0 = cyclicPos;
curMatch = _son[ptr0];
len0 = len;
}
}
MovePos();
}
while (--num != 0);
}
void NormalizeLinks(UInt32[] items, UInt32 numItems, UInt32 subValue)
{
for (UInt32 i = 0; i < numItems; i++)
{
UInt32 value = items[i];
if (value <= subValue)
value = kEmptyHashValue;
else
value -= subValue;
items[i] = value;
}
}
void Normalize()
{
UInt32 subValue = _pos - _cyclicBufferSize;
NormalizeLinks(_son, _cyclicBufferSize * 2, subValue);
NormalizeLinks(_hash, _hashSizeSum, subValue);
ReduceOffsets((Int32)subValue);
}
public void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; }
}
}

View File

@@ -1,148 +0,0 @@
using System;
namespace Compress.SevenZip.Compress.LZ
{
internal class InWindow
{
public Byte[] _bufferBase = null; // pointer to buffer with data
System.IO.Stream _stream;
UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done
bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream
UInt32 _pointerToLastSafePosition;
public UInt32 _bufferOffset;
public UInt32 _blockSize; // Size of Allocated memory block
public UInt32 _pos; // offset (from _buffer) of curent byte
UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos
UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos
public UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream
public void MoveBlock()
{
UInt32 offset = (UInt32)(_bufferOffset) + _pos - _keepSizeBefore;
// we need one additional byte, since MovePos moves on 1 byte.
if (offset > 0)
offset--;
UInt32 numBytes = (UInt32)(_bufferOffset) + _streamPos - offset;
// check negative offset ????
for (UInt32 i = 0; i < numBytes; i++)
_bufferBase[i] = _bufferBase[offset + i];
_bufferOffset -= offset;
}
public virtual void ReadBlock()
{
if (_streamEndWasReached)
return;
while (true)
{
int size = (int)((0 - _bufferOffset) + _blockSize - _streamPos);
if (size == 0)
return;
int numReadBytes = _stream != null ? _stream.Read(_bufferBase, (int)(_bufferOffset + _streamPos), size) : 0;
if (numReadBytes == 0)
{
_posLimit = _streamPos;
UInt32 pointerToPostion = _bufferOffset + _posLimit;
if (pointerToPostion > _pointerToLastSafePosition)
_posLimit = (UInt32)(_pointerToLastSafePosition - _bufferOffset);
_streamEndWasReached = true;
return;
}
_streamPos += (UInt32)numReadBytes;
if (_streamPos >= _pos + _keepSizeAfter)
_posLimit = _streamPos - _keepSizeAfter;
}
}
void Free() { _bufferBase = null; }
public void Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv)
{
_keepSizeBefore = keepSizeBefore;
_keepSizeAfter = keepSizeAfter;
UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv;
if (_bufferBase == null || _blockSize != blockSize)
{
Free();
_blockSize = blockSize;
_bufferBase = new Byte[_blockSize];
}
_pointerToLastSafePosition = _blockSize - keepSizeAfter;
_streamEndWasReached = false;
}
public void SetStream(System.IO.Stream stream)
{
_stream = stream;
if (_streamEndWasReached)
{
_streamEndWasReached = false;
if (IsDataStarved)
ReadBlock();
}
}
public void ReleaseStream() { _stream = null; }
public void Init()
{
_bufferOffset = 0;
_pos = 0;
_streamPos = 0;
_streamEndWasReached = false;
ReadBlock();
}
public void MovePos()
{
_pos++;
if (_pos > _posLimit)
{
UInt32 pointerToPostion = _bufferOffset + _pos;
if (pointerToPostion > _pointerToLastSafePosition)
MoveBlock();
ReadBlock();
}
}
public Byte GetIndexByte(Int32 index) { return _bufferBase[_bufferOffset + _pos + index]; }
// index + limit have not to exceed _keepSizeAfter;
public UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit)
{
if (_streamEndWasReached)
if ((_pos + index) + limit > _streamPos)
limit = _streamPos - (UInt32)(_pos + index);
distance++;
// Byte *pby = _buffer + (size_t)_pos + index;
UInt32 pby = _bufferOffset + _pos + (UInt32)index;
UInt32 i;
for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++) ;
return i;
}
public UInt32 GetNumAvailableBytes() { return _streamPos - _pos; }
public void ReduceOffsets(Int32 subValue)
{
_bufferOffset += (UInt32)subValue;
_posLimit -= (UInt32)subValue;
_pos -= (UInt32)subValue;
_streamPos -= (UInt32)subValue;
}
public bool IsDataStarved
{
get
{
return _streamPos - _pos < _keepSizeAfter;
}
}
}
}

View File

@@ -1,186 +0,0 @@
using Compress.SevenZip.Common;
namespace Compress.SevenZip.Compress.LZ
{
internal class OutWindow
{
byte[] _buffer = null;
int _windowSize = 0;
int _pos;
int _streamPos;
int _pendingLen;
int _pendingDist;
System.IO.Stream _stream;
public long Total;
public long Limit;
public void Create(int windowSize)
{
if (_windowSize != windowSize)
_buffer = new byte[windowSize];
else
_buffer[windowSize - 1] = 0;
_windowSize = windowSize;
_pos = 0;
_streamPos = 0;
_pendingLen = 0;
Total = 0;
Limit = 0;
}
public void Reset()
{
Create(_windowSize);
}
public void Init(System.IO.Stream stream)
{
ReleaseStream();
_stream = stream;
}
public void Train(System.IO.Stream stream)
{
long len = stream.Length;
int size = (len < _windowSize) ? (int)len : _windowSize;
stream.Position = len - size;
Total = 0;
Limit = size;
_pos = _windowSize - size;
CopyStream(stream, size);
if (_pos == _windowSize)
_pos = 0;
_streamPos = _pos;
}
public void ReleaseStream()
{
Flush();
_stream = null;
}
public void Flush()
{
if (_stream == null)
return;
int size = _pos - _streamPos;
if (size == 0)
return;
_stream.Write(_buffer, _streamPos, size);
if (_pos >= _windowSize)
_pos = 0;
_streamPos = _pos;
}
public void CopyBlock(int distance, int len)
{
int size = len;
int pos = _pos - distance - 1;
if (pos < 0)
pos += _windowSize;
for (; size > 0 && _pos < _windowSize && Total < Limit; size--)
{
if (pos >= _windowSize)
pos = 0;
_buffer[_pos++] = _buffer[pos++];
Total++;
if (_pos >= _windowSize)
Flush();
}
_pendingLen = size;
_pendingDist = distance;
}
public void PutByte(byte b)
{
_buffer[_pos++] = b;
Total++;
if (_pos >= _windowSize)
Flush();
}
public byte GetByte(int distance)
{
int pos = _pos - distance - 1;
if (pos < 0)
pos += _windowSize;
return _buffer[pos];
}
public int CopyStream(System.IO.Stream stream, int len)
{
int size = len;
while (size > 0 && _pos < _windowSize && Total < Limit)
{
int curSize = _windowSize - _pos;
if (curSize > Limit - Total)
curSize = (int)(Limit - Total);
if (curSize > size)
curSize = size;
int numReadBytes = stream.Read(_buffer, _pos, curSize);
if (numReadBytes == 0)
throw new DataErrorException();
size -= numReadBytes;
_pos += numReadBytes;
Total += numReadBytes;
if (_pos >= _windowSize)
Flush();
}
return len - size;
}
public void SetLimit(long size)
{
Limit = Total + size;
}
public bool HasSpace
{
get
{
return _pos < _windowSize && Total < Limit;
}
}
public bool HasPending
{
get
{
return _pendingLen > 0;
}
}
public int Read(byte[] buffer, int offset, int count)
{
if (_streamPos >= _pos)
return 0;
int size = _pos - _streamPos;
if (size > count)
size = count;
System.Buffer.BlockCopy(_buffer, _streamPos, buffer, offset, size);
_streamPos += size;
if (_streamPos >= _windowSize)
{
_pos = 0;
_streamPos = 0;
}
return size;
}
public void CopyPending()
{
if (_pendingLen > 0)
CopyBlock(_pendingDist, _pendingLen);
}
public int AvailableBytes
{
get
{
return _pos - _streamPos;
}
}
}
}

View File

@@ -1,74 +0,0 @@
namespace Compress.SevenZip.Compress.LZMA
{
internal abstract class Base
{
public const uint kNumRepDistances = 4;
public const uint kNumStates = 12;
// static byte []kLiteralNextStates = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5};
// static byte []kMatchNextStates = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};
// static byte []kRepNextStates = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};
// static byte []kShortRepNextStates = {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};
public struct State
{
public uint Index;
public void Init() { Index = 0; }
public void UpdateChar()
{
if (Index < 4) Index = 0;
else if (Index < 10) Index -= 3;
else Index -= 6;
}
public void UpdateMatch() { Index = (uint)(Index < 7 ? 7 : 10); }
public void UpdateRep() { Index = (uint)(Index < 7 ? 8 : 11); }
public void UpdateShortRep() { Index = (uint)(Index < 7 ? 9 : 11); }
public bool IsCharState() { return Index < 7; }
}
public const int kNumPosSlotBits = 6;
public const int kDicLogSizeMin = 0;
// public const int kDicLogSizeMax = 30;
// public const uint kDistTableSizeMax = kDicLogSizeMax * 2;
public const int kNumLenToPosStatesBits = 2; // it's for speed optimization
public const uint kNumLenToPosStates = 1 << kNumLenToPosStatesBits;
public const uint kMatchMinLen = 2;
public static uint GetLenToPosState(uint len)
{
len -= kMatchMinLen;
if (len < kNumLenToPosStates)
return len;
return (uint)(kNumLenToPosStates - 1);
}
public const int kNumAlignBits = 4;
public const uint kAlignTableSize = 1 << kNumAlignBits;
public const uint kAlignMask = (kAlignTableSize - 1);
public const uint kStartPosModelIndex = 4;
public const uint kEndPosModelIndex = 14;
public const uint kNumPosModels = kEndPosModelIndex - kStartPosModelIndex;
public const uint kNumFullDistances = 1 << ((int)kEndPosModelIndex / 2);
public const uint kNumLitPosStatesBitsEncodingMax = 4;
public const uint kNumLitContextBitsMax = 8;
public const int kNumPosStatesBitsMax = 4;
public const uint kNumPosStatesMax = (1 << kNumPosStatesBitsMax);
public const int kNumPosStatesBitsEncodingMax = 4;
public const uint kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax);
public const int kNumLowLenBits = 3;
public const int kNumMidLenBits = 3;
public const int kNumHighLenBits = 8;
public const uint kNumLowLenSymbols = 1 << kNumLowLenBits;
public const uint kNumMidLenSymbols = 1 << kNumMidLenBits;
public const uint kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols +
(1 << kNumHighLenBits);
public const uint kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1;
}
}

View File

@@ -1,404 +0,0 @@
using System;
using Compress.SevenZip.Common;
using Compress.SevenZip.Compress.RangeCoder;
namespace Compress.SevenZip.Compress.LZMA
{
internal class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream
{
class LenDecoder
{
BitDecoder m_Choice = new BitDecoder();
BitDecoder m_Choice2 = new BitDecoder();
BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax];
BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax];
BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits);
uint m_NumPosStates = 0;
public void Create(uint numPosStates)
{
for (uint posState = m_NumPosStates; posState < numPosStates; posState++)
{
m_LowCoder[posState] = new BitTreeDecoder(Base.kNumLowLenBits);
m_MidCoder[posState] = new BitTreeDecoder(Base.kNumMidLenBits);
}
m_NumPosStates = numPosStates;
}
public void Init()
{
m_Choice.Init();
for (uint posState = 0; posState < m_NumPosStates; posState++)
{
m_LowCoder[posState].Init();
m_MidCoder[posState].Init();
}
m_Choice2.Init();
m_HighCoder.Init();
}
public uint Decode(RangeCoder.Decoder rangeDecoder, uint posState)
{
if (m_Choice.Decode(rangeDecoder) == 0)
return m_LowCoder[posState].Decode(rangeDecoder);
else
{
uint symbol = Base.kNumLowLenSymbols;
if (m_Choice2.Decode(rangeDecoder) == 0)
symbol += m_MidCoder[posState].Decode(rangeDecoder);
else
{
symbol += Base.kNumMidLenSymbols;
symbol += m_HighCoder.Decode(rangeDecoder);
}
return symbol;
}
}
}
class LiteralDecoder
{
struct Decoder2
{
BitDecoder[] m_Decoders;
public void Create() { m_Decoders = new BitDecoder[0x300]; }
public void Init() { for (int i = 0; i < 0x300; i++) m_Decoders[i].Init(); }
public byte DecodeNormal(RangeCoder.Decoder rangeDecoder)
{
uint symbol = 1;
do
symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder);
while (symbol < 0x100);
return (byte)symbol;
}
public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, byte matchByte)
{
uint symbol = 1;
do
{
uint matchBit = (uint)(matchByte >> 7) & 1;
matchByte <<= 1;
uint bit = m_Decoders[((1 + matchBit) << 8) + symbol].Decode(rangeDecoder);
symbol = (symbol << 1) | bit;
if (matchBit != bit)
{
while (symbol < 0x100)
symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder);
break;
}
}
while (symbol < 0x100);
return (byte)symbol;
}
}
Decoder2[] m_Coders;
int m_NumPrevBits;
int m_NumPosBits;
uint m_PosMask;
public void Create(int numPosBits, int numPrevBits)
{
if (m_Coders != null && m_NumPrevBits == numPrevBits &&
m_NumPosBits == numPosBits)
return;
m_NumPosBits = numPosBits;
m_PosMask = ((uint)1 << numPosBits) - 1;
m_NumPrevBits = numPrevBits;
uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);
m_Coders = new Decoder2[numStates];
for (uint i = 0; i < numStates; i++)
m_Coders[i].Create();
}
public void Init()
{
uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);
for (uint i = 0; i < numStates; i++)
m_Coders[i].Init();
}
uint GetState(uint pos, byte prevByte)
{ return ((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits)); }
public byte DecodeNormal(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte)
{ return m_Coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); }
public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte, byte matchByte)
{ return m_Coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); }
};
LZ.OutWindow m_OutWindow;
BitDecoder[] m_IsMatchDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax];
BitDecoder[] m_IsRepDecoders = new BitDecoder[Base.kNumStates];
BitDecoder[] m_IsRepG0Decoders = new BitDecoder[Base.kNumStates];
BitDecoder[] m_IsRepG1Decoders = new BitDecoder[Base.kNumStates];
BitDecoder[] m_IsRepG2Decoders = new BitDecoder[Base.kNumStates];
BitDecoder[] m_IsRep0LongDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax];
BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates];
BitDecoder[] m_PosDecoders = new BitDecoder[Base.kNumFullDistances - Base.kEndPosModelIndex];
BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits);
LenDecoder m_LenDecoder = new LenDecoder();
LenDecoder m_RepLenDecoder = new LenDecoder();
LiteralDecoder m_LiteralDecoder = new LiteralDecoder();
int m_DictionarySize;
uint m_PosStateMask;
Base.State state = new Base.State();
uint rep0, rep1, rep2, rep3;
public Decoder()
{
m_DictionarySize = -1;
for (int i = 0; i < Base.kNumLenToPosStates; i++)
m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits);
}
void CreateDictionary()
{
if (m_DictionarySize < 0)
throw new InvalidParamException();
m_OutWindow = new LZ.OutWindow();
int blockSize = Math.Max(m_DictionarySize, (1 << 12));
m_OutWindow.Create(blockSize);
}
void SetLiteralProperties(int lp, int lc)
{
if (lp > 8)
throw new InvalidParamException();
if (lc > 8)
throw new InvalidParamException();
m_LiteralDecoder.Create(lp, lc);
}
void SetPosBitsProperties(int pb)
{
if (pb > Base.kNumPosStatesBitsMax)
throw new InvalidParamException();
uint numPosStates = (uint)1 << pb;
m_LenDecoder.Create(numPosStates);
m_RepLenDecoder.Create(numPosStates);
m_PosStateMask = numPosStates - 1;
}
void Init()
{
uint i;
for (i = 0; i < Base.kNumStates; i++)
{
for (uint j = 0; j <= m_PosStateMask; j++)
{
uint index = (i << Base.kNumPosStatesBitsMax) + j;
m_IsMatchDecoders[index].Init();
m_IsRep0LongDecoders[index].Init();
}
m_IsRepDecoders[i].Init();
m_IsRepG0Decoders[i].Init();
m_IsRepG1Decoders[i].Init();
m_IsRepG2Decoders[i].Init();
}
m_LiteralDecoder.Init();
for (i = 0; i < Base.kNumLenToPosStates; i++)
m_PosSlotDecoder[i].Init();
// m_PosSpecDecoder.Init();
for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++)
m_PosDecoders[i].Init();
m_LenDecoder.Init();
m_RepLenDecoder.Init();
m_PosAlignDecoder.Init();
state.Init();
rep0 = 0;
rep1 = 0;
rep2 = 0;
rep3 = 0;
}
public void Code(System.IO.Stream inStream, System.IO.Stream outStream,
Int64 inSize, Int64 outSize, ICodeProgress progress)
{
if (m_OutWindow == null)
CreateDictionary();
m_OutWindow.Init(outStream);
if (outSize > 0)
m_OutWindow.SetLimit(outSize);
else
m_OutWindow.SetLimit(Int64.MaxValue - m_OutWindow.Total);
RangeCoder.Decoder rangeDecoder = new RangeCoder.Decoder();
rangeDecoder.Init(inStream);
Code(m_DictionarySize, m_OutWindow, rangeDecoder);
m_OutWindow.ReleaseStream();
rangeDecoder.ReleaseStream();
if (!rangeDecoder.IsFinished || (inSize > 0 && rangeDecoder.Total != inSize))
throw new DataErrorException();
if (m_OutWindow.HasPending)
throw new DataErrorException();
m_OutWindow = null;
}
internal bool Code(int dictionarySize, LZ.OutWindow outWindow, RangeCoder.Decoder rangeDecoder)
{
int dictionarySizeCheck = Math.Max(dictionarySize, 1);
outWindow.CopyPending();
while (outWindow.HasSpace)
{
uint posState = (uint)outWindow.Total & m_PosStateMask;
if (m_IsMatchDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(rangeDecoder) == 0)
{
byte b;
byte prevByte = outWindow.GetByte(0);
if (!state.IsCharState())
b = m_LiteralDecoder.DecodeWithMatchByte(rangeDecoder,
(uint)outWindow.Total, prevByte, outWindow.GetByte((int)rep0));
else
b = m_LiteralDecoder.DecodeNormal(rangeDecoder, (uint)outWindow.Total, prevByte);
outWindow.PutByte(b);
state.UpdateChar();
}
else
{
uint len;
if (m_IsRepDecoders[state.Index].Decode(rangeDecoder) == 1)
{
if (m_IsRepG0Decoders[state.Index].Decode(rangeDecoder) == 0)
{
if (m_IsRep0LongDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(rangeDecoder) == 0)
{
state.UpdateShortRep();
outWindow.PutByte(outWindow.GetByte((int)rep0));
continue;
}
}
else
{
UInt32 distance;
if (m_IsRepG1Decoders[state.Index].Decode(rangeDecoder) == 0)
{
distance = rep1;
}
else
{
if (m_IsRepG2Decoders[state.Index].Decode(rangeDecoder) == 0)
distance = rep2;
else
{
distance = rep3;
rep3 = rep2;
}
rep2 = rep1;
}
rep1 = rep0;
rep0 = distance;
}
len = m_RepLenDecoder.Decode(rangeDecoder, posState) + Base.kMatchMinLen;
state.UpdateRep();
}
else
{
rep3 = rep2;
rep2 = rep1;
rep1 = rep0;
len = Base.kMatchMinLen + m_LenDecoder.Decode(rangeDecoder, posState);
state.UpdateMatch();
uint posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(rangeDecoder);
if (posSlot >= Base.kStartPosModelIndex)
{
int numDirectBits = (int)((posSlot >> 1) - 1);
rep0 = ((2 | (posSlot & 1)) << numDirectBits);
if (posSlot < Base.kEndPosModelIndex)
rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders,
rep0 - posSlot - 1, rangeDecoder, numDirectBits);
else
{
rep0 += (rangeDecoder.DecodeDirectBits(
numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits);
rep0 += m_PosAlignDecoder.ReverseDecode(rangeDecoder);
}
}
else
rep0 = posSlot;
}
if (rep0 >= outWindow.Total || rep0 >= dictionarySizeCheck)
{
if (rep0 == 0xFFFFFFFF)
return true;
throw new DataErrorException();
}
outWindow.CopyBlock((int)rep0, (int)len);
}
}
return false;
}
public void SetDecoderProperties(byte[] properties)
{
if (properties.Length < 1)
throw new InvalidParamException();
int lc = properties[0] % 9;
int remainder = properties[0] / 9;
int lp = remainder % 5;
int pb = remainder / 5;
if (pb > Base.kNumPosStatesBitsMax)
throw new InvalidParamException();
SetLiteralProperties(lp, lc);
SetPosBitsProperties(pb);
Init();
if (properties.Length >= 5)
{
m_DictionarySize = 0;
for (int i = 0; i < 4; i++)
m_DictionarySize += properties[1 + i] << (i * 8);
}
}
public void Train(System.IO.Stream stream)
{
if (m_OutWindow == null)
CreateDictionary();
m_OutWindow.Train(stream);
}
/*
public override bool CanRead { get { return true; }}
public override bool CanWrite { get { return true; }}
public override bool CanSeek { get { return true; }}
public override long Length { get { return 0; }}
public override long Position
{
get { return 0; }
set { }
}
public override void Flush() { }
public override int Read(byte[] buffer, int offset, int count)
{
return 0;
}
public override void Write(byte[] buffer, int offset, int count)
{
}
public override long Seek(long offset, System.IO.SeekOrigin origin)
{
return 0;
}
public override void SetLength(long value) {}
*/
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,57 +0,0 @@
using Compress.SevenZip.Common;
namespace Compress.SevenZip.Compress.LZMA
{
public class LzmaEncoderProperties
{
internal CoderPropID[] propIDs;
internal object[] properties;
public LzmaEncoderProperties()
: this(false)
{
}
public LzmaEncoderProperties(bool eos)
: this(eos, 1 << 20)
{
}
public LzmaEncoderProperties(bool eos, int dictionary)
: this(eos, dictionary, 32)
{
}
public LzmaEncoderProperties(bool eos, int dictionary, int numFastBytes)
{
int posStateBits = 2;
int litContextBits = 4;
int litPosBits = 0;
int algorithm = 2;
string mf = "bt4";
propIDs = new CoderPropID[]
{
CoderPropID.DictionarySize,
CoderPropID.PosStateBits,
CoderPropID.LitContextBits,
CoderPropID.LitPosBits,
CoderPropID.Algorithm,
CoderPropID.NumFastBytes,
CoderPropID.MatchFinder,
CoderPropID.EndMarker
};
properties = new object[]
{
dictionary,
posStateBits,
litContextBits,
litPosBits,
algorithm,
numFastBytes,
mf,
eos
};
}
}
}

View File

@@ -1,318 +0,0 @@
using System;
using System.IO;
using Compress.SevenZip.Common;
using Compress.SevenZip.Compress.LZ;
namespace Compress.SevenZip.Compress.LZMA
{
public class LzmaStream : Stream
{
private Stream inputStream;
private long inputSize;
private long outputSize;
private int dictionarySize;
private OutWindow outWindow = new OutWindow();
private RangeCoder.Decoder rangeDecoder = new RangeCoder.Decoder();
private Decoder decoder;
private long position = 0;
private bool endReached = false;
private long availableBytes;
private long rangeDecoderLimit;
private long inputPosition = 0;
// LZMA2
private bool isLZMA2;
private bool uncompressedChunk = false;
private bool needDictReset = true;
private bool needProps = true;
private byte[] props = new byte[5];
private Encoder encoder;
public LzmaStream(byte[] properties, Stream inputStream)
: this(properties, inputStream, -1, -1, null, properties.Length < 5)
{
}
public LzmaStream(byte[] properties, Stream inputStream, long inputSize)
: this(properties, inputStream, inputSize, -1, null, properties.Length < 5)
{
}
public LzmaStream(byte[] properties, Stream inputStream, long inputSize, long outputSize)
: this(properties, inputStream, inputSize, outputSize, null, properties.Length < 5)
{
}
public LzmaStream(byte[] properties, Stream inputStream, long inputSize, long outputSize,
Stream presetDictionary, bool isLZMA2)
{
this.inputStream = inputStream;
this.inputSize = inputSize;
this.outputSize = outputSize;
this.isLZMA2 = isLZMA2;
if (!isLZMA2)
{
dictionarySize = BitConverter.ToInt32(properties, 1);
outWindow.Create(dictionarySize);
if (presetDictionary != null)
outWindow.Train(presetDictionary);
rangeDecoder.Init(inputStream);
decoder = new Decoder();
decoder.SetDecoderProperties(properties);
props = properties;
availableBytes = outputSize < 0 ? long.MaxValue : outputSize;
rangeDecoderLimit = inputSize;
}
else
{
dictionarySize = 2 | (properties[0] & 1);
dictionarySize <<= (properties[0] >> 1) + 11;
outWindow.Create(dictionarySize);
if (presetDictionary != null)
{
outWindow.Train(presetDictionary);
needDictReset = false;
}
props = new byte[1];
availableBytes = 0;
}
}
public LzmaStream(LzmaEncoderProperties properties, bool isLZMA2, Stream outputStream)
: this(properties, isLZMA2, null, outputStream)
{
}
public LzmaStream(LzmaEncoderProperties properties, bool isLZMA2, Stream presetDictionary, Stream outputStream)
{
this.isLZMA2 = isLZMA2;
availableBytes = 0;
endReached = true;
if (isLZMA2)
throw new NotImplementedException();
encoder = new Encoder();
encoder.SetCoderProperties(properties.propIDs, properties.properties);
MemoryStream propStream = new MemoryStream(5);
encoder.WriteCoderProperties(propStream);
props = propStream.ToArray();
encoder.SetStreams(null, outputStream, -1, -1);
if (presetDictionary != null)
encoder.Train(presetDictionary);
}
public override bool CanRead
{
get { return encoder == null; }
}
public override bool CanSeek
{
get { return false; }
}
public override bool CanWrite
{
get { return encoder != null; }
}
public override void Flush()
{
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (encoder != null)
position = encoder.Code(null, true);
}
base.Dispose(disposing);
}
public override long Length
{
get { return position + availableBytes; }
}
public override long Position
{
get
{
return position;
}
set
{
throw new NotImplementedException();
}
}
public override int Read(byte[] buffer, int offset, int count)
{
if (endReached)
return 0;
int total = 0;
while (total < count)
{
if (availableBytes == 0)
{
if (isLZMA2)
decodeChunkHeader();
else
endReached = true;
if (endReached)
break;
}
int toProcess = count - total;
if (toProcess > availableBytes)
toProcess = (int)availableBytes;
outWindow.SetLimit(toProcess);
if (uncompressedChunk)
{
inputPosition += outWindow.CopyStream(inputStream, toProcess);
}
else if (decoder.Code(dictionarySize, outWindow, rangeDecoder)
&& outputSize < 0)
{
availableBytes = outWindow.AvailableBytes;
}
int read = outWindow.Read(buffer, offset, toProcess);
total += read;
offset += read;
position += read;
availableBytes -= read;
if (availableBytes == 0 && !uncompressedChunk)
{
rangeDecoder.ReleaseStream();
if (!rangeDecoder.IsFinished || (rangeDecoderLimit >= 0 && rangeDecoder.Total != rangeDecoderLimit))
throw new DataErrorException();
inputPosition += rangeDecoder.Total;
if (outWindow.HasPending)
throw new DataErrorException();
}
}
if (endReached)
{
if (inputSize >= 0 && inputPosition != inputSize)
throw new DataErrorException();
if (outputSize >= 0 && position != outputSize)
throw new DataErrorException();
}
return total;
}
private void decodeChunkHeader()
{
int control = inputStream.ReadByte();
inputPosition++;
if (control == 0x00)
{
endReached = true;
return;
}
if (control >= 0xE0 || control == 0x01)
{
needProps = true;
needDictReset = false;
outWindow.Reset();
}
else if (needDictReset)
throw new DataErrorException();
if (control >= 0x80)
{
uncompressedChunk = false;
availableBytes = (control & 0x1F) << 16;
availableBytes += (inputStream.ReadByte() << 8) + inputStream.ReadByte() + 1;
inputPosition += 2;
rangeDecoderLimit = (inputStream.ReadByte() << 8) + inputStream.ReadByte() + 1;
inputPosition += 2;
if (control >= 0xC0)
{
needProps = false;
props[0] = (byte)inputStream.ReadByte();
inputPosition++;
decoder = new Decoder();
decoder.SetDecoderProperties(props);
}
else if (needProps)
throw new DataErrorException();
else if (control >= 0xA0)
{
decoder = new Decoder();
decoder.SetDecoderProperties(props);
}
rangeDecoder.Init(inputStream);
}
else if (control > 0x02)
throw new DataErrorException();
else
{
uncompressedChunk = true;
availableBytes = (inputStream.ReadByte() << 8) + inputStream.ReadByte() + 1;
inputPosition += 2;
}
}
public override long Seek(long offset, SeekOrigin origin)
{
if (origin != SeekOrigin.Current)
throw new NotImplementedException();
byte[] tmpBuff = new byte[1024];
long sizeToGo = offset;
while (sizeToGo > 0)
{
int sizenow = sizeToGo > 1024 ? 1024 : (int)sizeToGo;
Read(tmpBuff, 0, sizenow);
sizeToGo -= sizenow;
}
return offset;
}
public override void SetLength(long value)
{
throw new NotImplementedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
if (encoder != null)
position = encoder.Code(new MemoryStream(buffer, offset, count), false);
}
public byte[] Properties
{
get
{
return props;
}
}
}
}

View File

@@ -1,75 +0,0 @@
using System.Text;
namespace Compress.SevenZip.Compress.PPmd.H
{
internal class FreqData : Pointer
{
internal const int Size = 6;
// struct FreqData
// {
// ushort SummFreq;
// STATE _PACK_ATTR * Stats;
// };
internal FreqData(byte[] Memory)
: base(Memory)
{
}
internal int SummFreq
{
get
{
return Utility.readShortLittleEndian(Memory, Address) & 0xffff;
}
set
{
Utility.WriteLittleEndian(Memory, Address, (short)value);
}
}
internal FreqData Initialize(byte[] mem)
{
return base.Initialize<FreqData>(mem);
}
internal void IncrementSummFreq(int dSummFreq)
{
Utility.incShortLittleEndian(Memory, Address, (short)dSummFreq);
}
internal int GetStats()
{
return Utility.readIntLittleEndian(Memory, Address + 2);
}
internal virtual void SetStats(State state)
{
SetStats(state.Address);
}
internal void SetStats(int state)
{
Utility.WriteLittleEndian(Memory, Address + 2, state);
}
public override System.String ToString()
{
StringBuilder buffer = new StringBuilder();
buffer.Append("FreqData[");
buffer.Append("\n Address=");
buffer.Append(Address);
buffer.Append("\n size=");
buffer.Append(Size);
buffer.Append("\n summFreq=");
buffer.Append(SummFreq);
buffer.Append("\n stats=");
buffer.Append(GetStats());
buffer.Append("\n]");
return buffer.ToString();
}
}
}

View File

@@ -1,945 +0,0 @@
using System.IO;
using System.Text;
using Decoder = Compress.SevenZip.Compress.RangeCoder.Decoder;
namespace Compress.SevenZip.Compress.PPmd.H
{
internal class ModelPPM
{
private void InitBlock()
{
for (int i = 0; i < 25; i++)
{
SEE2Cont[i] = new SEE2Context[16];
}
for (int i2 = 0; i2 < 128; i2++)
{
binSumm[i2] = new int[64];
}
}
public SubAllocator SubAlloc
{
get
{
return subAlloc;
}
}
virtual public SEE2Context DummySEE2Cont
{
get
{
return dummySEE2Cont;
}
}
virtual public int InitRL
{
get
{
return initRL;
}
}
virtual public int EscCount
{
get
{
return escCount;
}
set
{
this.escCount = value & 0xff;
}
}
virtual public int[] CharMask
{
get
{
return charMask;
}
}
virtual public int NumMasked
{
get
{
return numMasked;
}
set
{
this.numMasked = value;
}
}
virtual public int PrevSuccess
{
get
{
return prevSuccess;
}
set
{
this.prevSuccess = value & 0xff;
}
}
virtual public int InitEsc
{
get
{
return initEsc;
}
set
{
this.initEsc = value;
}
}
virtual public int RunLength
{
get
{
return runLength;
}
set
{
this.runLength = value;
}
}
virtual public int HiBitsFlag
{
get
{
return hiBitsFlag;
}
set
{
this.hiBitsFlag = value & 0xff;
}
}
virtual public int[][] BinSumm
{
get
{
return binSumm;
}
}
internal RangeCoder Coder
{
get
{
return coder;
}
}
internal State FoundState
{
get
{
return foundState;
}
}
virtual public byte[] Heap
{
get
{
return subAlloc.Heap;
}
}
virtual public int OrderFall
{
get
{
return orderFall;
}
}
public const int MAX_O = 64; /* maximum allowed model order */
public const int INT_BITS = 7;
public const int PERIOD_BITS = 7;
//UPGRADE_NOTE: Final was removed from the declaration of 'TOT_BITS '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
public static readonly int TOT_BITS = INT_BITS + PERIOD_BITS;
//UPGRADE_NOTE: Final was removed from the declaration of 'INTERVAL '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
public static readonly int INTERVAL = 1 << INT_BITS;
//UPGRADE_NOTE: Final was removed from the declaration of 'BIN_SCALE '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
public static readonly int BIN_SCALE = 1 << TOT_BITS;
public const int MAX_FREQ = 124;
private SEE2Context[][] SEE2Cont = new SEE2Context[25][];
private SEE2Context dummySEE2Cont;
private PPMContext minContext; //medContext
private PPMContext maxContext;
private State foundState; // found next state transition
private int numMasked, initEsc, orderFall, maxOrder, runLength, initRL;
private int[] charMask = new int[256];
private int[] NS2Indx = new int[256];
private int[] NS2BSIndx = new int[256];
private int[] HB2Flag = new int[256];
// byte EscCount, PrevSuccess, HiBitsFlag;
private int escCount, prevSuccess, hiBitsFlag;
private int[][] binSumm = new int[128][]; // binary SEE-contexts
private RangeCoder coder;
private SubAllocator subAlloc = new SubAllocator();
private static int[] InitBinEsc = new int[] { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051 };
// Temp fields
//UPGRADE_NOTE: Final was removed from the declaration of 'tempState1 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
private State tempState1 = new State(null);
//UPGRADE_NOTE: Final was removed from the declaration of 'tempState2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
private State tempState2 = new State(null);
//UPGRADE_NOTE: Final was removed from the declaration of 'tempState3 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
private State tempState3 = new State(null);
//UPGRADE_NOTE: Final was removed from the declaration of 'tempState4 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
private State tempState4 = new State(null);
//UPGRADE_NOTE: Final was removed from the declaration of 'tempStateRef1 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
private StateRef tempStateRef1 = new StateRef();
//UPGRADE_NOTE: Final was removed from the declaration of 'tempStateRef2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
private StateRef tempStateRef2 = new StateRef();
//UPGRADE_NOTE: Final was removed from the declaration of 'tempPPMContext1 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
private PPMContext tempPPMContext1 = new PPMContext(null);
//UPGRADE_NOTE: Final was removed from the declaration of 'tempPPMContext2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
private PPMContext tempPPMContext2 = new PPMContext(null);
//UPGRADE_NOTE: Final was removed from the declaration of 'tempPPMContext3 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
private PPMContext tempPPMContext3 = new PPMContext(null);
//UPGRADE_NOTE: Final was removed from the declaration of 'tempPPMContext4 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
private PPMContext tempPPMContext4 = new PPMContext(null);
//UPGRADE_NOTE: Final was removed from the declaration of 'ps '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
private int[] ps = new int[MAX_O];
public ModelPPM()
{
InitBlock();
minContext = null;
maxContext = null;
//medContext = null;
}
private void restartModelRare()
{
Utility.Fill(charMask, 0);
subAlloc.initSubAllocator();
initRL = -(maxOrder < 12 ? maxOrder : 12) - 1;
int addr = subAlloc.allocContext();
minContext.Address = addr;
maxContext.Address = addr;
minContext.setSuffix(0);
orderFall = maxOrder;
minContext.NumStats = 256;
minContext.FreqData.SummFreq = minContext.NumStats + 1;
addr = subAlloc.allocUnits(256 / 2);
foundState.Address = addr;
minContext.FreqData.SetStats(addr);
State state = new State(subAlloc.Heap);
addr = minContext.FreqData.GetStats();
runLength = initRL;
prevSuccess = 0;
for (int i = 0; i < 256; i++)
{
state.Address = addr + i * State.Size;
state.Symbol = i;
state.Freq = 1;
state.SetSuccessor(0);
}
for (int i = 0; i < 128; i++)
{
for (int k = 0; k < 8; k++)
{
for (int m = 0; m < 64; m += 8)
{
binSumm[i][k + m] = BIN_SCALE - InitBinEsc[k] / (i + 2);
}
}
}
for (int i = 0; i < 25; i++)
{
for (int k = 0; k < 16; k++)
{
SEE2Cont[i][k].Initialize(5 * i + 10);
}
}
}
private void startModelRare(int MaxOrder)
{
int i, k, m, Step;
escCount = 1;
this.maxOrder = MaxOrder;
restartModelRare();
// Bug Fixed
NS2BSIndx[0] = 0;
NS2BSIndx[1] = 2;
for (int j = 0; j < 9; j++)
{
NS2BSIndx[2 + j] = 4;
}
for (int j = 0; j < 256 - 11; j++)
{
NS2BSIndx[11 + j] = 6;
}
for (i = 0; i < 3; i++)
{
NS2Indx[i] = i;
}
for (m = i, k = 1, Step = 1; i < 256; i++)
{
NS2Indx[i] = m;
if ((--k) == 0)
{
k = ++Step;
m++;
}
}
for (int j = 0; j < 0x40; j++)
{
HB2Flag[j] = 0;
}
for (int j = 0; j < 0x100 - 0x40; j++)
{
HB2Flag[0x40 + j] = 0x08;
}
dummySEE2Cont.Shift = PERIOD_BITS;
}
private void clearMask()
{
escCount = 1;
Utility.Fill(charMask, 0);
}
public virtual int decodeChar()
{
// Debug
//subAlloc.dumpHeap();
if (minContext.Address <= subAlloc.PText || minContext.Address > subAlloc.HeapEnd)
{
return (-1);
}
if (minContext.NumStats != 1)
{
if (minContext.FreqData.GetStats() <= subAlloc.PText || minContext.FreqData.GetStats() > subAlloc.HeapEnd)
{
return (-1);
}
if (!minContext.decodeSymbol1(this))
{
return (-1);
}
}
else
{
minContext.decodeBinSymbol(this);
}
coder.Decode();
while (foundState.Address == 0)
{
coder.AriDecNormalize();
do
{
orderFall++;
minContext.Address = minContext.getSuffix(); // =MinContext->Suffix;
if (minContext.Address <= subAlloc.PText || minContext.Address > subAlloc.HeapEnd)
{
return (-1);
}
}
while (minContext.NumStats == numMasked);
if (!minContext.decodeSymbol2(this))
{
return (-1);
}
coder.Decode();
}
int Symbol = foundState.Symbol;
if ((orderFall == 0) && foundState.GetSuccessor() > subAlloc.PText)
{
// MinContext=MaxContext=FoundState->Successor;
int addr = foundState.GetSuccessor();
minContext.Address = addr;
maxContext.Address = addr;
}
else
{
updateModel();
//this.foundState.Address=foundState.Address);//TODO just 4 debugging
if (escCount == 0)
{
clearMask();
}
}
coder.AriDecNormalize(); // ARI_DEC_NORMALIZE(Coder.code,Coder.low,Coder.range,Coder.UnpackRead);
return (Symbol);
}
public virtual SEE2Context[][] getSEE2Cont()
{
return SEE2Cont;
}
public virtual void incEscCount(int dEscCount)
{
EscCount = EscCount + dEscCount;
}
public virtual void incRunLength(int dRunLength)
{
RunLength = RunLength + dRunLength;
}
public virtual int[] getHB2Flag()
{
return HB2Flag;
}
public virtual int[] getNS2BSIndx()
{
return NS2BSIndx;
}
public virtual int[] getNS2Indx()
{
return NS2Indx;
}
private int createSuccessors(bool Skip, State p1)
{
//State upState = tempState1.Initialize(null);
StateRef upState = tempStateRef2;
State tempState = tempState1.Initialize(Heap);
// PPM_CONTEXT* pc=MinContext, * UpBranch=FoundState->Successor;
PPMContext pc = tempPPMContext1.Initialize(Heap);
pc.Address = minContext.Address;
PPMContext upBranch = tempPPMContext2.Initialize(Heap);
upBranch.Address = foundState.GetSuccessor();
// STATE * p, * ps[MAX_O], ** pps=ps;
State p = tempState2.Initialize(Heap);
int pps = 0;
bool noLoop = false;
if (!Skip)
{
ps[pps++] = foundState.Address; // *pps++ = FoundState;
if (pc.getSuffix() == 0)
{
noLoop = true;
}
}
if (!noLoop)
{
bool loopEntry = false;
if (p1.Address != 0)
{
p.Address = p1.Address;
pc.Address = pc.getSuffix(); // =pc->Suffix;
loopEntry = true;
}
do
{
if (!loopEntry)
{
pc.Address = pc.getSuffix(); // pc=pc->Suffix;
if (pc.NumStats != 1)
{
p.Address = pc.FreqData.GetStats(); // p=pc->U.Stats
if (p.Symbol != foundState.Symbol)
{
do
{
p.IncrementAddress();
}
while (p.Symbol != foundState.Symbol);
}
}
else
{
p.Address = pc.getOneState().Address; // p=&(pc->OneState);
}
} // LOOP_ENTRY:
loopEntry = false;
if (p.GetSuccessor() != upBranch.Address)
{
pc.Address = p.GetSuccessor(); // =p->Successor;
break;
}
ps[pps++] = p.Address;
}
while (pc.getSuffix() != 0);
} // NO_LOOP:
if (pps == 0)
{
return pc.Address;
}
upState.Symbol = Heap[upBranch.Address]; // UpState.Symbol=*(byte*)
// UpBranch;
// UpState.Successor=(PPM_CONTEXT*) (((byte*) UpBranch)+1);
upState.SetSuccessor(upBranch.Address + 1); //TODO check if +1 necessary
if (pc.NumStats != 1)
{
if (pc.Address <= subAlloc.PText)
{
return (0);
}
p.Address = pc.FreqData.GetStats();
if (p.Symbol != upState.Symbol)
{
do
{
p.IncrementAddress();
}
while (p.Symbol != upState.Symbol);
}
int cf = p.Freq - 1;
int s0 = pc.FreqData.SummFreq - pc.NumStats - cf;
// UpState.Freq=1+((2*cf <= s0)?(5*cf > s0):((2*cf+3*s0-1)/(2*s0)));
upState.Freq = 1 + ((2 * cf <= s0) ? (5 * cf > s0 ? 1 : 0) : ((2 * cf + 3 * s0 - 1) / (2 * s0)));
}
else
{
upState.Freq = pc.getOneState().Freq; // UpState.Freq=pc->OneState.Freq;
}
do
{
// pc = pc->createChild(this,*--pps,UpState);
tempState.Address = ps[--pps];
pc.Address = pc.createChild(this, tempState, upState);
if (pc.Address == 0)
{
return 0;
}
}
while (pps != 0);
return pc.Address;
}
private void updateModelRestart()
{
restartModelRare();
escCount = 0;
}
private void updateModel()
{
//System.out.println("ModelPPM.updateModel()");
// STATE fs = *FoundState, *p = NULL;
StateRef fs = tempStateRef1;
fs.Values = foundState;
State p = tempState3.Initialize(Heap);
State tempState = tempState4.Initialize(Heap);
PPMContext pc = tempPPMContext3.Initialize(Heap);
PPMContext successor = tempPPMContext4.Initialize(Heap);
int ns1, ns, cf, sf, s0;
pc.Address = minContext.getSuffix();
if (fs.Freq < MAX_FREQ / 4 && pc.Address != 0)
{
if (pc.NumStats != 1)
{
p.Address = pc.FreqData.GetStats();
if (p.Symbol != fs.Symbol)
{
do
{
p.IncrementAddress();
}
while (p.Symbol != fs.Symbol);
tempState.Address = p.Address - State.Size;
if (p.Freq >= tempState.Freq)
{
State.PPMDSwap(p, tempState);
p.DecrementAddress();
}
}
if (p.Freq < MAX_FREQ - 9)
{
p.IncrementFreq(2);
pc.FreqData.IncrementSummFreq(2);
}
}
else
{
p.Address = pc.getOneState().Address;
if (p.Freq < 32)
{
p.IncrementFreq(1);
}
}
}
if (orderFall == 0)
{
foundState.SetSuccessor(createSuccessors(true, p));
minContext.Address = foundState.GetSuccessor();
maxContext.Address = foundState.GetSuccessor();
if (minContext.Address == 0)
{
updateModelRestart();
return;
}
return;
}
subAlloc.Heap[subAlloc.PText] = (byte)fs.Symbol;
subAlloc.incPText();
successor.Address = subAlloc.PText;
if (subAlloc.PText >= subAlloc.FakeUnitsStart)
{
updateModelRestart();
return;
}
// // Debug
// subAlloc.dumpHeap();
if (fs.GetSuccessor() != 0)
{
if (fs.GetSuccessor() <= subAlloc.PText)
{
fs.SetSuccessor(createSuccessors(false, p));
if (fs.GetSuccessor() == 0)
{
updateModelRestart();
return;
}
}
if (--orderFall == 0)
{
successor.Address = fs.GetSuccessor();
if (maxContext.Address != minContext.Address)
{
subAlloc.decPText(1);
}
}
}
else
{
foundState.SetSuccessor(successor.Address);
fs.SetSuccessor(minContext);
}
// // Debug
// subAlloc.dumpHeap();
ns = minContext.NumStats;
s0 = minContext.FreqData.SummFreq - (ns) - (fs.Freq - 1);
for (pc.Address = maxContext.Address; pc.Address != minContext.Address; pc.Address = pc.getSuffix())
{
if ((ns1 = pc.NumStats) != 1)
{
if ((ns1 & 1) == 0)
{
//System.out.println(ns1);
pc.FreqData.SetStats(subAlloc.expandUnits(pc.FreqData.GetStats(), Utility.URShift(ns1, 1)));
if (pc.FreqData.GetStats() == 0)
{
updateModelRestart();
return;
}
}
// bug fixed
// int sum = ((2 * ns1 < ns) ? 1 : 0) +
// 2 * ((4 * ((ns1 <= ns) ? 1 : 0)) & ((pc.getFreqData()
// .getSummFreq() <= 8 * ns1) ? 1 : 0));
int sum = ((2 * ns1 < ns) ? 1 : 0) + 2 * (((4 * ns1 <= ns) ? 1 : 0) & ((pc.FreqData.SummFreq <= 8 * ns1) ? 1 : 0));
pc.FreqData.IncrementSummFreq(sum);
}
else
{
p.Address = subAlloc.allocUnits(1);
if (p.Address == 0)
{
updateModelRestart();
return;
}
p.SetValues(pc.getOneState());
pc.FreqData.SetStats(p);
if (p.Freq < MAX_FREQ / 4 - 1)
{
p.IncrementFreq(p.Freq);
}
else
{
p.Freq = MAX_FREQ - 4;
}
pc.FreqData.SummFreq = (p.Freq + initEsc + (ns > 3 ? 1 : 0));
}
cf = 2 * fs.Freq * (pc.FreqData.SummFreq + 6);
sf = s0 + pc.FreqData.SummFreq;
if (cf < 6 * sf)
{
cf = 1 + (cf > sf ? 1 : 0) + (cf >= 4 * sf ? 1 : 0);
pc.FreqData.IncrementSummFreq(3);
}
else
{
cf = 4 + (cf >= 9 * sf ? 1 : 0) + (cf >= 12 * sf ? 1 : 0) + (cf >= 15 * sf ? 1 : 0);
pc.FreqData.IncrementSummFreq(cf);
}
p.Address = pc.FreqData.GetStats() + ns1 * State.Size;
p.SetSuccessor(successor);
p.Symbol = fs.Symbol;
p.Freq = cf;
pc.NumStats = ++ns1;
}
int address = fs.GetSuccessor();
maxContext.Address = address;
minContext.Address = address;
//TODO-----debug
// int pos = minContext.getFreqData().getStats();
// State a = new State(getHeap());
// a.Address=pos);
// pos+=State.size;
// a.Address=pos);
//--dbg end
return;
}
// Debug
public override System.String ToString()
{
StringBuilder buffer = new StringBuilder();
buffer.Append("ModelPPM[");
buffer.Append("\n numMasked=");
buffer.Append(numMasked);
buffer.Append("\n initEsc=");
buffer.Append(initEsc);
buffer.Append("\n orderFall=");
buffer.Append(orderFall);
buffer.Append("\n maxOrder=");
buffer.Append(maxOrder);
buffer.Append("\n runLength=");
buffer.Append(runLength);
buffer.Append("\n initRL=");
buffer.Append(initRL);
buffer.Append("\n escCount=");
buffer.Append(escCount);
buffer.Append("\n prevSuccess=");
buffer.Append(prevSuccess);
buffer.Append("\n foundState=");
buffer.Append(foundState);
buffer.Append("\n coder=");
buffer.Append(coder);
buffer.Append("\n subAlloc=");
buffer.Append(subAlloc);
buffer.Append("\n]");
return buffer.ToString();
}
// Debug
// public void dumpHeap() {
// subAlloc.dumpHeap();
// }
internal bool decodeInit(Stream stream, int maxOrder, int maxMemory)
{
if (stream != null)
coder = new RangeCoder(stream);
if (maxOrder == 1)
{
subAlloc.stopSubAllocator();
return (false);
}
subAlloc.startSubAllocator(maxMemory);
minContext = new PPMContext(Heap);
//medContext = new PPMContext(Heap);
maxContext = new PPMContext(Heap);
foundState = new State(Heap);
dummySEE2Cont = new SEE2Context();
for (int i = 0; i < 25; i++)
{
for (int j = 0; j < 16; j++)
{
SEE2Cont[i][j] = new SEE2Context();
}
}
startModelRare(maxOrder);
return (minContext.Address != 0);
}
internal void nextContext()
{
int addr = foundState.GetSuccessor();
if (orderFall == 0 && addr > subAlloc.PText)
{
minContext.Address = addr;
maxContext.Address = addr;
}
else
updateModel();
}
public int decodeChar(Decoder decoder)
{
if (minContext.NumStats != 1)
{
State s = tempState1.Initialize(Heap);
s.Address = minContext.FreqData.GetStats();
int i;
int count, hiCnt;
if ((count = (int)decoder.GetThreshold((uint)minContext.FreqData.SummFreq)) < (hiCnt = s.Freq))
{
byte symbol;
decoder.Decode(0, (uint)s.Freq);
symbol = (byte)s.Symbol;
minContext.update1_0(this, s.Address);
nextContext();
return symbol;
}
prevSuccess = 0;
i = minContext.NumStats - 1;
do
{
s.IncrementAddress();
if ((hiCnt += s.Freq) > count)
{
byte symbol;
decoder.Decode((uint)(hiCnt - s.Freq), (uint)s.Freq);
symbol = (byte)s.Symbol;
minContext.update1(this, s.Address);
nextContext();
return symbol;
}
}
while (--i > 0);
if (count >= minContext.FreqData.SummFreq)
return -2;
hiBitsFlag = HB2Flag[foundState.Symbol];
decoder.Decode((uint)hiCnt, (uint)(minContext.FreqData.SummFreq - hiCnt));
for (i = 0; i < 256; i++)
charMask[i] = -1;
charMask[s.Symbol] = 0;
i = minContext.NumStats - 1;
do
{
s.DecrementAddress();
charMask[s.Symbol] = 0;
}
while (--i > 0);
}
else
{
State rs = tempState1.Initialize(Heap);
rs.Address = minContext.getOneState().Address;
hiBitsFlag = getHB2Flag()[foundState.Symbol];
int off1 = rs.Freq - 1;
int off2 = minContext.getArrayIndex(this, rs);
int bs = binSumm[off1][off2];
if (decoder.DecodeBit((uint)bs, 14) == 0)
{
byte symbol;
binSumm[off1][off2] = (bs + INTERVAL - minContext.getMean(bs, PERIOD_BITS, 2)) & 0xFFFF;
foundState.Address = rs.Address;
symbol = (byte)rs.Symbol;
rs.IncrementFreq((rs.Freq < 128) ? 1 : 0);
prevSuccess = 1;
incRunLength(1);
nextContext();
return symbol;
}
bs = (bs - minContext.getMean(bs, PERIOD_BITS, 2)) & 0xFFFF;
binSumm[off1][off2] = bs;
initEsc = PPMContext.ExpEscape[Utility.URShift(bs, 10)];
int i;
for (i = 0; i < 256; i++)
charMask[i] = -1;
charMask[rs.Symbol] = 0;
prevSuccess = 0;
}
for (; ; )
{
State s = tempState1.Initialize(Heap);
int i;
int freqSum, count, hiCnt;
SEE2Context see;
int num, numMasked = minContext.NumStats;
do
{
orderFall++;
minContext.Address = minContext.getSuffix();
if (minContext.Address <= subAlloc.PText || minContext.Address > subAlloc.HeapEnd)
return -1;
}
while (minContext.NumStats == numMasked);
hiCnt = 0;
s.Address = minContext.FreqData.GetStats();
i = 0;
num = minContext.NumStats - numMasked;
do
{
int k = charMask[s.Symbol];
hiCnt += s.Freq & k;
minContext.ps[i] = s.Address;
s.IncrementAddress();
i -= k;
}
while (i != num);
see = minContext.makeEscFreq(this, numMasked, out freqSum);
freqSum += hiCnt;
count = (int)decoder.GetThreshold((uint)freqSum);
if (count < hiCnt)
{
byte symbol;
State ps = tempState2.Initialize(Heap);
for (hiCnt = 0, i = 0, ps.Address = minContext.ps[i]; (hiCnt += ps.Freq) <= count; i++, ps.Address = minContext.ps[i]) ;
s.Address = ps.Address;
decoder.Decode((uint)(hiCnt - s.Freq), (uint)s.Freq);
see.update();
symbol = (byte)s.Symbol;
minContext.update2(this, s.Address);
updateModel();
return symbol;
}
if (count >= freqSum)
return -2;
decoder.Decode((uint)hiCnt, (uint)(freqSum - hiCnt));
see.Summ = see.Summ + freqSum;
do
{
s.Address = minContext.ps[--i];
charMask[s.Symbol] = 0;
}
while (i != 0);
}
}
}
}

View File

@@ -1,563 +0,0 @@
using System.Text;
namespace Compress.SevenZip.Compress.PPmd.H
{
internal class PPMContext : Pointer
{
internal FreqData FreqData
{
get
{
return freqData;
}
set
{
this.freqData.SummFreq = value.SummFreq;
this.freqData.SetStats(value.GetStats());
}
}
virtual public int NumStats
{
get
{
if (Memory != null)
{
numStats = Utility.readShortLittleEndian(Memory, Address) & 0xffff;
}
return numStats;
}
set
{
this.numStats = value & 0xffff;
if (Memory != null)
{
Utility.WriteLittleEndian(Memory, Address, (short)value);
}
}
}
//UPGRADE_NOTE: Final was removed from the declaration of 'unionSize '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
//UPGRADE_NOTE: The initialization of 'unionSize' was moved to static method 'SharpCompress.Unpack.PPM.PPMContext'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1005'"
private static readonly int unionSize;
//UPGRADE_NOTE: Final was removed from the declaration of 'size '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
public static readonly int size = 2 + unionSize + 4; // 12
// ushort NumStats;
private int numStats; // determines if feqData or onstate is used
// (1==onestate)
//UPGRADE_NOTE: Final was removed from the declaration of 'freqData '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
private FreqData freqData; // -\
// |-> union
//UPGRADE_NOTE: Final was removed from the declaration of 'oneState '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
private State oneState; // -/
private int suffix; // pointer ppmcontext
//UPGRADE_NOTE: Final was removed from the declaration of 'ExpEscape'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
public static readonly int[] ExpEscape = new int[] { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
// Temp fields
//UPGRADE_NOTE: Final was removed from the declaration of 'tempState1 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
private State tempState1 = new State(null);
//UPGRADE_NOTE: Final was removed from the declaration of 'tempState2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
private State tempState2 = new State(null);
//UPGRADE_NOTE: Final was removed from the declaration of 'tempState3 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
private State tempState3 = new State(null);
//UPGRADE_NOTE: Final was removed from the declaration of 'tempState4 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
private State tempState4 = new State(null);
//UPGRADE_NOTE: Final was removed from the declaration of 'tempState5 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
private State tempState5 = new State(null);
private PPMContext tempPPMContext = null;
//UPGRADE_NOTE: Final was removed from the declaration of 'ps '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
internal int[] ps = new int[256];
public PPMContext(byte[] Memory)
: base(Memory)
{
oneState = new State(Memory);
freqData = new FreqData(Memory);
}
internal PPMContext Initialize(byte[] mem)
{
oneState.Initialize(mem);
freqData.Initialize(mem);
return base.Initialize<PPMContext>(mem);
}
internal State getOneState()
{
return oneState;
}
internal void setOneState(StateRef oneState)
{
this.oneState.SetValues(oneState);
}
internal int getSuffix()
{
if (Memory != null)
{
suffix = Utility.readIntLittleEndian(Memory, Address + 8);
}
return suffix;
}
internal void setSuffix(PPMContext suffix)
{
setSuffix(suffix.Address);
}
internal void setSuffix(int suffix)
{
this.suffix = suffix;
if (Memory != null)
{
Utility.WriteLittleEndian(Memory, Address + 8, suffix);
}
}
internal override int Address
{
get
{
return base.Address;
}
set
{
base.Address = value;
oneState.Address = value + 2;
freqData.Address = value + 2;
}
}
private PPMContext getTempPPMContext(byte[] Memory)
{
if (tempPPMContext == null)
{
tempPPMContext = new PPMContext(null);
}
return tempPPMContext.Initialize(Memory);
}
internal int createChild(ModelPPM model, State pStats, StateRef firstState)
{
PPMContext pc = getTempPPMContext(model.SubAlloc.Heap);
pc.Address = model.SubAlloc.allocContext();
if (pc != null)
{
pc.NumStats = 1;
pc.setOneState(firstState);
pc.setSuffix(this);
pStats.SetSuccessor(pc);
}
return pc.Address;
}
internal void rescale(ModelPPM model)
{
int OldNS = NumStats, i = NumStats - 1, Adder, EscFreq;
// STATE* p1, * p;
State p1 = new State(model.Heap);
State p = new State(model.Heap);
State temp = new State(model.Heap);
for (p.Address = model.FoundState.Address; p.Address != freqData.GetStats(); p.DecrementAddress())
{
temp.Address = p.Address - State.Size;
State.PPMDSwap(p, temp);
}
temp.Address = freqData.GetStats();
temp.IncrementFreq(4);
freqData.IncrementSummFreq(4);
EscFreq = freqData.SummFreq - p.Freq;
Adder = (model.OrderFall != 0) ? 1 : 0;
p.Freq = Utility.URShift((p.Freq + Adder), 1);
freqData.SummFreq = p.Freq;
do
{
p.IncrementAddress();
EscFreq -= p.Freq;
p.Freq = Utility.URShift((p.Freq + Adder), 1);
freqData.IncrementSummFreq(p.Freq);
temp.Address = p.Address - State.Size;
if (p.Freq > temp.Freq)
{
p1.Address = p.Address;
StateRef tmp = new StateRef();
tmp.Values = p1;
State temp2 = new State(model.Heap);
State temp3 = new State(model.Heap);
do
{
// p1[0]=p1[-1];
temp2.Address = p1.Address - State.Size;
p1.SetValues(temp2);
p1.DecrementAddress();
temp3.Address = p1.Address - State.Size;
}
while (p1.Address != freqData.GetStats() && tmp.Freq > temp3.Freq);
p1.SetValues(tmp);
}
}
while (--i != 0);
if (p.Freq == 0)
{
do
{
i++;
p.DecrementAddress();
}
while (p.Freq == 0);
EscFreq += i;
NumStats = NumStats - i;
if (NumStats == 1)
{
StateRef tmp = new StateRef();
temp.Address = freqData.GetStats();
tmp.Values = temp;
// STATE tmp=*U.Stats;
do
{
// tmp.Freq-=(tmp.Freq >> 1)
tmp.DecrementFreq(Utility.URShift(tmp.Freq, 1));
EscFreq = Utility.URShift(EscFreq, 1);
}
while (EscFreq > 1);
model.SubAlloc.freeUnits(freqData.GetStats(), Utility.URShift((OldNS + 1), 1));
oneState.SetValues(tmp);
model.FoundState.Address = oneState.Address;
return;
}
}
EscFreq -= Utility.URShift(EscFreq, 1);
freqData.IncrementSummFreq(EscFreq);
int n0 = Utility.URShift((OldNS + 1), 1), n1 = Utility.URShift((NumStats + 1), 1);
if (n0 != n1)
{
freqData.SetStats(model.SubAlloc.shrinkUnits(freqData.GetStats(), n0, n1));
}
model.FoundState.Address = freqData.GetStats();
}
internal int getArrayIndex(ModelPPM Model, State rs)
{
PPMContext tempSuffix = getTempPPMContext(Model.SubAlloc.Heap);
tempSuffix.Address = getSuffix();
int ret = 0;
ret += Model.PrevSuccess;
ret += Model.getNS2BSIndx()[tempSuffix.NumStats - 1];
ret += Model.HiBitsFlag + 2 * Model.getHB2Flag()[rs.Symbol];
ret += ((Utility.URShift(Model.RunLength, 26)) & 0x20);
return ret;
}
internal int getMean(int summ, int shift, int round)
{
return (Utility.URShift((summ + (1 << (shift - round))), (shift)));
}
internal void decodeBinSymbol(ModelPPM model)
{
State rs = tempState1.Initialize(model.Heap);
rs.Address = oneState.Address; // State&
model.HiBitsFlag = model.getHB2Flag()[model.FoundState.Symbol];
int off1 = rs.Freq - 1;
int off2 = getArrayIndex(model, rs);
int bs = model.BinSumm[off1][off2];
if (model.Coder.GetCurrentShiftCount(ModelPPM.TOT_BITS) < bs)
{
model.FoundState.Address = rs.Address;
rs.IncrementFreq((rs.Freq < 128) ? 1 : 0);
model.Coder.SubRange.LowCount = 0;
model.Coder.SubRange.HighCount = bs;
bs = ((bs + ModelPPM.INTERVAL - getMean(bs, ModelPPM.PERIOD_BITS, 2)) & 0xffff);
model.BinSumm[off1][off2] = bs;
model.PrevSuccess = 1;
model.incRunLength(1);
}
else
{
model.Coder.SubRange.LowCount = bs;
bs = (bs - getMean(bs, ModelPPM.PERIOD_BITS, 2)) & 0xFFFF;
model.BinSumm[off1][off2] = bs;
model.Coder.SubRange.HighCount = ModelPPM.BIN_SCALE;
model.InitEsc = ExpEscape[Utility.URShift(bs, 10)];
model.NumMasked = 1;
model.CharMask[rs.Symbol] = model.EscCount;
model.PrevSuccess = 0;
model.FoundState.Address = 0;
}
//int a = 0;//TODO just 4 debugging
}
// public static void ppmdSwap(ModelPPM model, StatePtr state1, StatePtr state2)
// {
// byte[] bytes = model.getSubAlloc().getHeap();
// int p1 = state1.Address;
// int p2 = state2.Address;
//
// for (int i = 0; i < StatePtr.size; i++) {
// byte temp = bytes[p1+i];
// bytes[p1+i] = bytes[p2+i];
// bytes[p2+i] = temp;
// }
// state1.Address=p1);
// state2.Address=p2);
// }
internal void update1(ModelPPM model, int p)
{
model.FoundState.Address = p;
model.FoundState.IncrementFreq(4);
freqData.IncrementSummFreq(4);
State p0 = tempState3.Initialize(model.Heap);
State p1 = tempState4.Initialize(model.Heap);
p0.Address = p;
p1.Address = p - State.Size;
if (p0.Freq > p1.Freq)
{
State.PPMDSwap(p0, p1);
model.FoundState.Address = p1.Address;
if (p1.Freq > ModelPPM.MAX_FREQ)
rescale(model);
}
}
internal void update1_0(ModelPPM model, int p)
{
model.FoundState.Address = p;
model.PrevSuccess = 2 * model.FoundState.Freq > freqData.SummFreq ? 1 : 0;
model.incRunLength(model.PrevSuccess);
freqData.IncrementSummFreq(4);
model.FoundState.IncrementFreq(4);
if (model.FoundState.Freq > ModelPPM.MAX_FREQ)
rescale(model);
}
internal bool decodeSymbol2(ModelPPM model)
{
long count;
int hiCnt, i = NumStats - model.NumMasked;
SEE2Context psee2c = makeEscFreq2(model, i);
RangeCoder coder = model.Coder;
// STATE* ps[256], ** pps=ps, * p=U.Stats-1;
State p = tempState1.Initialize(model.Heap);
State temp = tempState2.Initialize(model.Heap);
p.Address = freqData.GetStats() - State.Size;
int pps = 0;
hiCnt = 0;
do
{
do
{
p.IncrementAddress(); // p++;
}
while (model.CharMask[p.Symbol] == model.EscCount);
hiCnt += p.Freq;
ps[pps++] = p.Address;
}
while (--i != 0);
coder.SubRange.incScale(hiCnt);
count = coder.CurrentCount;
if (count >= coder.SubRange.Scale)
{
return false;
}
pps = 0;
p.Address = ps[pps];
if (count < hiCnt)
{
hiCnt = 0;
while ((hiCnt += p.Freq) <= count)
{
p.Address = ps[++pps]; // p=*++pps;
}
coder.SubRange.HighCount = hiCnt;
coder.SubRange.LowCount = hiCnt - p.Freq;
psee2c.update();
update2(model, p.Address);
}
else
{
coder.SubRange.LowCount = hiCnt;
coder.SubRange.HighCount = coder.SubRange.Scale;
i = NumStats - model.NumMasked; // ->NumMasked;
pps--;
do
{
temp.Address = ps[++pps]; // (*++pps)
model.CharMask[temp.Symbol] = model.EscCount;
}
while (--i != 0);
psee2c.incSumm((int)coder.SubRange.Scale);
model.NumMasked = NumStats;
}
return (true);
}
internal void update2(ModelPPM model, int p)
{
State temp = tempState5.Initialize(model.Heap);
temp.Address = p;
model.FoundState.Address = p;
model.FoundState.IncrementFreq(4);
freqData.IncrementSummFreq(4);
if (temp.Freq > ModelPPM.MAX_FREQ)
{
rescale(model);
}
model.incEscCount(1);
model.RunLength = model.InitRL;
}
private SEE2Context makeEscFreq2(ModelPPM model, int Diff)
{
SEE2Context psee2c;
int numStats = NumStats;
if (numStats != 256)
{
PPMContext suff = getTempPPMContext(model.Heap);
suff.Address = getSuffix();
int idx1 = model.getNS2Indx()[Diff - 1];
int idx2 = 0;
idx2 += ((Diff < suff.NumStats - numStats) ? 1 : 0);
idx2 += 2 * ((freqData.SummFreq < 11 * numStats) ? 1 : 0);
idx2 += 4 * ((model.NumMasked > Diff) ? 1 : 0);
idx2 += model.HiBitsFlag;
psee2c = model.getSEE2Cont()[idx1][idx2];
model.Coder.SubRange.Scale = psee2c.Mean;
}
else
{
psee2c = model.DummySEE2Cont;
model.Coder.SubRange.Scale = 1;
}
return psee2c;
}
internal SEE2Context makeEscFreq(ModelPPM model, int numMasked, out int escFreq)
{
SEE2Context psee2c;
int numStats = NumStats;
int nonMasked = numStats - numMasked;
if (numStats != 256)
{
PPMContext suff = getTempPPMContext(model.Heap);
suff.Address = getSuffix();
int idx1 = model.getNS2Indx()[nonMasked - 1];
int idx2 = 0;
idx2 += ((nonMasked < suff.NumStats - numStats) ? 1 : 0);
idx2 += 2 * ((freqData.SummFreq < 11 * numStats) ? 1 : 0);
idx2 += 4 * ((numMasked > nonMasked) ? 1 : 0);
idx2 += model.HiBitsFlag;
psee2c = model.getSEE2Cont()[idx1][idx2];
escFreq = psee2c.Mean;
}
else
{
psee2c = model.DummySEE2Cont;
escFreq = 1;
}
return psee2c;
}
internal bool decodeSymbol1(ModelPPM model)
{
RangeCoder coder = model.Coder;
coder.SubRange.Scale = freqData.SummFreq;
State p = new State(model.Heap);
p.Address = freqData.GetStats();
int i, HiCnt;
long count = coder.CurrentCount;
if (count >= coder.SubRange.Scale)
{
return false;
}
if (count < (HiCnt = p.Freq))
{
coder.SubRange.HighCount = HiCnt;
model.PrevSuccess = (2 * HiCnt > coder.SubRange.Scale) ? 1 : 0;
model.incRunLength(model.PrevSuccess);
HiCnt += 4;
model.FoundState.Address = p.Address;
model.FoundState.Freq = HiCnt;
freqData.IncrementSummFreq(4);
if (HiCnt > ModelPPM.MAX_FREQ)
{
rescale(model);
}
coder.SubRange.LowCount = 0;
return true;
}
else
{
if (model.FoundState.Address == 0)
{
return (false);
}
}
model.PrevSuccess = 0;
int numStats = NumStats;
i = numStats - 1;
while ((HiCnt += p.IncrementAddress().Freq) <= count)
{
if (--i == 0)
{
model.HiBitsFlag = model.getHB2Flag()[model.FoundState.Symbol];
coder.SubRange.LowCount = HiCnt;
model.CharMask[p.Symbol] = model.EscCount;
model.NumMasked = numStats;
i = numStats - 1;
model.FoundState.Address = 0;
do
{
model.CharMask[p.DecrementAddress().Symbol] = model.EscCount;
}
while (--i != 0);
coder.SubRange.HighCount = coder.SubRange.Scale;
return (true);
}
}
coder.SubRange.LowCount = HiCnt - p.Freq;
coder.SubRange.HighCount = HiCnt;
update1(model, p.Address);
return (true);
}
public override System.String ToString()
{
StringBuilder buffer = new StringBuilder();
buffer.Append("PPMContext[");
buffer.Append("\n Address=");
buffer.Append(Address);
buffer.Append("\n size=");
buffer.Append(size);
buffer.Append("\n numStats=");
buffer.Append(NumStats);
buffer.Append("\n Suffix=");
buffer.Append(getSuffix());
buffer.Append("\n freqData=");
buffer.Append(freqData);
buffer.Append("\n oneState=");
buffer.Append(oneState);
buffer.Append("\n]");
return buffer.ToString();
}
static PPMContext()
{
unionSize = System.Math.Max(FreqData.Size, State.Size);
}
}
}

View File

@@ -1,34 +0,0 @@
namespace Compress.SevenZip.Compress.PPmd.H
{
internal abstract class Pointer
{
/// <summary> Initialize the object with the array (may be null)</summary>
/// <param name="mem">the byte array
/// </param>
internal Pointer(byte[] mem)
{
Memory = mem;
}
internal byte[] Memory
{
get;
private set;
}
internal virtual int Address
{
get;
set;
}
protected T Initialize<T>(byte[] mem)
where T : Pointer
{
Memory = mem;
Address = 0;
return this as T;
}
}
}

View File

@@ -1,183 +0,0 @@
using System.IO;
using System.Text;
namespace Compress.SevenZip.Compress.PPmd.H
{
internal class RangeCoder
{
internal const int TOP = 1 << 24;
internal const int BOT = 1 << 15;
internal const long UintMask = 0xFFFFffffL;
// uint low, code, range;
private long low, code, range;
private Stream stream;
internal RangeCoder(Stream stream)
{
this.stream = stream;
Init();
}
private void Init()
{
this.SubRange = new SubRange();
low = code = 0L;
range = 0xFFFFffffL;
for (int i = 0; i < 4; i++)
{
code = ((code << 8) | Char) & UintMask;
}
}
internal int CurrentCount
{
get
{
range = (range / SubRange.Scale) & UintMask;
return (int)((code - low) / (range));
}
}
private long Char
{
get
{
if (stream != null)
return stream.ReadByte();
return -1;
}
}
internal SubRange SubRange
{
get;
private set;
}
internal long GetCurrentShiftCount(int SHIFT)
{
range = Utility.URShift(range, SHIFT);
return ((code - low) / (range)) & UintMask;
}
internal void Decode()
{
low = (low + (range * SubRange.LowCount)) & UintMask;
range = (range * (SubRange.HighCount - SubRange.LowCount)) & UintMask;
}
internal void AriDecNormalize()
{
// while ((low ^ (low + range)) < TOP || range < BOT && ((range = -low & (BOT - 1)) != 0 ? true : true))
// {
// code = ((code << 8) | unpackRead.getChar()&0xff)&uintMask;
// range = (range << 8)&uintMask;
// low = (low << 8)&uintMask;
// }
// Rewrote for clarity
bool c2 = false;
while ((low ^ (low + range)) < TOP || (c2 = range < BOT))
{
if (c2)
{
range = (-low & (BOT - 1)) & UintMask;
c2 = false;
}
code = ((code << 8) | Char) & UintMask;
range = (range << 8) & UintMask;
low = (low << 8) & UintMask;
}
}
// Debug
public override System.String ToString()
{
StringBuilder buffer = new StringBuilder();
buffer.Append("RangeCoder[");
buffer.Append("\n low=");
buffer.Append(low);
buffer.Append("\n code=");
buffer.Append(code);
buffer.Append("\n range=");
buffer.Append(range);
buffer.Append("\n subrange=");
buffer.Append(SubRange);
buffer.Append("]");
return buffer.ToString();
}
}
internal class SubRange
{
// uint LowCount, HighCount, scale;
private long lowCount, highCount, scale;
internal void incScale(int dScale)
{
Scale = Scale + dScale;
}
internal long HighCount
{
get
{
return highCount;
}
set
{
this.highCount = value & RangeCoder.UintMask;
}
}
internal long LowCount
{
get
{
return lowCount & RangeCoder.UintMask;
}
set
{
this.lowCount = value & RangeCoder.UintMask;
}
}
internal long Scale
{
get
{
return scale;
}
set
{
this.scale = value & RangeCoder.UintMask;
}
}
// Debug
public override System.String ToString()
{
StringBuilder buffer = new StringBuilder();
buffer.Append("SubRange[");
buffer.Append("\n lowCount=");
buffer.Append(lowCount);
buffer.Append("\n highCount=");
buffer.Append(highCount);
buffer.Append("\n scale=");
buffer.Append(scale);
buffer.Append("]");
return buffer.ToString();
}
}
}

View File

@@ -1,125 +0,0 @@
namespace Compress.SevenZip.Compress.PPmd.H
{
internal class RarMemBlock : Pointer
{
public const int size = 12;
private int stamp, NU;
private int next, prev; // Pointer RarMemBlock
public RarMemBlock(byte[] Memory)
: base(Memory)
{
}
internal int Stamp
{
get
{
if (Memory != null)
{
stamp = Utility.readShortLittleEndian(Memory, Address) & 0xffff;
}
return stamp;
}
set
{
this.stamp = value;
if (Memory != null)
{
Utility.WriteLittleEndian(Memory, Address, (short)value);
}
}
}
internal void InsertAt(RarMemBlock p)
{
RarMemBlock temp = new RarMemBlock(Memory);
SetPrev(p.Address);
temp.Address = GetPrev();
SetNext(temp.GetNext()); // prev.getNext();
temp.SetNext(this); // prev.setNext(this);
temp.Address = GetNext();
temp.SetPrev(this); // next.setPrev(this);
}
internal void Remove()
{
RarMemBlock temp = new RarMemBlock(Memory);
temp.Address = GetPrev();
temp.SetNext(GetNext()); // prev.setNext(next);
temp.Address = GetNext();
temp.SetPrev(GetPrev()); // next.setPrev(prev);
// next = -1;
// prev = -1;
}
internal int GetNext()
{
if (Memory != null)
{
next = Utility.readIntLittleEndian(Memory, Address + 4);
}
return next;
}
internal void SetNext(RarMemBlock next)
{
SetNext(next.Address);
}
internal void SetNext(int next)
{
this.next = next;
if (Memory != null)
{
Utility.WriteLittleEndian(Memory, Address + 4, next);
}
}
internal int GetNU()
{
if (Memory != null)
{
NU = Utility.readShortLittleEndian(Memory, Address + 2) & 0xffff;
}
return NU;
}
internal void SetNU(int nu)
{
NU = nu & 0xffff;
if (Memory != null)
{
Utility.WriteLittleEndian(Memory, Address + 2, (short)nu);
}
}
internal int GetPrev()
{
if (Memory != null)
{
prev = Utility.readIntLittleEndian(Memory, Address + 8);
}
return prev;
}
internal void SetPrev(RarMemBlock prev)
{
SetPrev(prev.Address);
}
internal void SetPrev(int prev)
{
this.prev = prev;
if (Memory != null)
{
Utility.WriteLittleEndian(Memory, Address + 8, prev);
}
}
}
}

View File

@@ -1,53 +0,0 @@
using System.Text;
namespace Compress.SevenZip.Compress.PPmd.H
{
internal class RarNode : Pointer
{
private int next; //rarnode pointer
public const int size = 4;
public RarNode(byte[] Memory)
: base(Memory)
{
}
internal int GetNext()
{
if (Memory != null)
{
next = Utility.readIntLittleEndian(Memory, Address);
}
return next;
}
internal void SetNext(RarNode next)
{
SetNext(next.Address);
}
internal void SetNext(int next)
{
this.next = next;
if (Memory != null)
{
Utility.WriteLittleEndian(Memory, Address, next);
}
}
public override string ToString()
{
StringBuilder buffer = new StringBuilder();
buffer.Append("State[");
buffer.Append("\n Address=");
buffer.Append(Address);
buffer.Append("\n size=");
buffer.Append(size);
buffer.Append("\n next=");
buffer.Append(GetNext());
buffer.Append("\n]");
return buffer.ToString();
}
}
}

View File

@@ -1,107 +0,0 @@
using System.Text;
namespace Compress.SevenZip.Compress.PPmd.H
{
internal class SEE2Context
{
virtual public int Mean
{
get
{
int retVal = Utility.URShift(summ, shift);
summ -= retVal;
return retVal + ((retVal == 0) ? 1 : 0);
}
}
virtual public int Count
{
get
{
return count;
}
set
{
this.count = value & 0xff;
}
}
virtual public int Shift
{
get
{
return shift;
}
set
{
this.shift = value & 0xff;
}
}
virtual public int Summ
{
get
{
return summ;
}
set
{
this.summ = value & 0xffff;
}
}
public const int size = 4;
// ushort Summ;
private int summ;
// byte Shift;
private int shift;
// byte Count;
private int count;
public void Initialize(int initVal)
{
shift = (ModelPPM.PERIOD_BITS - 4) & 0xff;
summ = (initVal << shift) & 0xffff;
count = 4;
}
public virtual void update()
{
if (shift < ModelPPM.PERIOD_BITS && --count == 0)
{
summ += summ;
count = (3 << shift++);
}
summ &= 0xffff;
count &= 0xff;
shift &= 0xff;
}
public virtual void incSumm(int dSumm)
{
Summ = Summ + dSumm;
}
public override System.String ToString()
{
StringBuilder buffer = new StringBuilder();
buffer.Append("SEE2Context[");
buffer.Append("\n size=");
buffer.Append(size);
buffer.Append("\n summ=");
buffer.Append(summ);
buffer.Append("\n shift=");
buffer.Append(shift);
buffer.Append("\n count=");
buffer.Append(count);
buffer.Append("\n]");
return buffer.ToString();
}
}
}

View File

@@ -1,120 +0,0 @@
using System;
using System.Text;
namespace Compress.SevenZip.Compress.PPmd.H
{
internal class State : Pointer
{
internal const int Size = 6;
internal State(byte[] Memory)
: base(Memory)
{
}
internal int Symbol
{
get
{
return Memory[Address] & 0xff;
}
set
{
Memory[Address] = (byte)value;
}
}
internal int Freq
{
get
{
return Memory[Address + 1] & 0xff;
}
set
{
Memory[Address + 1] = (byte)value;
}
}
internal State Initialize(byte[] mem)
{
return base.Initialize<State>(mem);
}
internal void IncrementFreq(int dFreq)
{
Memory[Address + 1] = (byte)(Memory[Address + 1] + dFreq);
}
internal int GetSuccessor()
{
return Utility.readIntLittleEndian(Memory, Address + 2);
}
internal void SetSuccessor(PPMContext successor)
{
SetSuccessor(successor.Address);
}
internal void SetSuccessor(int successor)
{
Utility.WriteLittleEndian(Memory, Address + 2, successor);
}
internal void SetValues(StateRef state)
{
Symbol = state.Symbol;
Freq = state.Freq;
SetSuccessor(state.GetSuccessor());
}
internal void SetValues(State ptr)
{
Array.Copy(ptr.Memory, ptr.Address, Memory, Address, Size);
}
internal State DecrementAddress()
{
Address = Address - Size;
return this;
}
internal State IncrementAddress()
{
Address = Address + Size;
return this;
}
internal static void PPMDSwap(State ptr1, State ptr2)
{
byte[] mem1 = ptr1.Memory, mem2 = ptr2.Memory;
for (int i = 0, pos1 = ptr1.Address, pos2 = ptr2.Address; i < Size; i++, pos1++, pos2++)
{
byte temp = mem1[pos1];
mem1[pos1] = mem2[pos2];
mem2[pos2] = temp;
}
}
public override System.String ToString()
{
StringBuilder buffer = new StringBuilder();
buffer.Append("State[");
buffer.Append("\n Address=");
buffer.Append(Address);
buffer.Append("\n size=");
buffer.Append(Size);
buffer.Append("\n symbol=");
buffer.Append(Symbol);
buffer.Append("\n freq=");
buffer.Append(Freq);
buffer.Append("\n successor=");
buffer.Append(GetSuccessor());
buffer.Append("\n]");
return buffer.ToString();
}
}
}

View File

@@ -1,90 +0,0 @@
using System.Text;
namespace Compress.SevenZip.Compress.PPmd.H
{
internal class StateRef
{
private int symbol;
private int freq;
private int successor; // pointer ppmcontext
internal int Symbol
{
get
{
return symbol;
}
set
{
this.symbol = value & 0xff;
}
}
internal int Freq
{
get
{
return freq;
}
set
{
this.freq = value & 0xff;
}
}
internal State Values
{
set
{
Freq = value.Freq;
SetSuccessor(value.GetSuccessor());
Symbol = value.Symbol;
}
}
public virtual void IncrementFreq(int dFreq)
{
freq = (freq + dFreq) & 0xff;
}
public virtual void DecrementFreq(int dFreq)
{
freq = (freq - dFreq) & 0xff;
}
public virtual int GetSuccessor()
{
return successor;
}
public virtual void SetSuccessor(PPMContext successor)
{
SetSuccessor(successor.Address);
}
public virtual void SetSuccessor(int successor)
{
this.successor = successor;
}
public override System.String ToString()
{
StringBuilder buffer = new StringBuilder();
buffer.Append("State[");
buffer.Append("\n symbol=");
buffer.Append(Symbol);
buffer.Append("\n freq=");
buffer.Append(Freq);
buffer.Append("\n successor=");
buffer.Append(GetSuccessor());
buffer.Append("\n]");
return buffer.ToString();
}
}
}

View File

@@ -1,489 +0,0 @@
using System;
using System.Text;
namespace Compress.SevenZip.Compress.PPmd.H
{
internal class SubAllocator
{
virtual public int FakeUnitsStart
{
get
{
return fakeUnitsStart;
}
set
{
this.fakeUnitsStart = value;
}
}
virtual public int HeapEnd
{
get
{
return heapEnd;
}
}
virtual public int PText
{
get
{
return pText;
}
set
{
pText = value;
}
}
virtual public int UnitsStart
{
get
{
return unitsStart;
}
set
{
this.unitsStart = value;
}
}
virtual public byte[] Heap
{
get
{
return heap;
}
}
//UPGRADE_NOTE: Final was removed from the declaration of 'N4 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
public const int N1 = 4;
public const int N2 = 4;
public const int N3 = 4;
public static readonly int N4 = (128 + 3 - 1 * N1 - 2 * N2 - 3 * N3) / 4;
//UPGRADE_NOTE: Final was removed from the declaration of 'N_INDEXES '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
public static readonly int N_INDEXES = N1 + N2 + N3 + N4;
//UPGRADE_NOTE: Final was removed from the declaration of 'UNIT_SIZE '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
//UPGRADE_NOTE: The initialization of 'UNIT_SIZE' was moved to static method 'SharpCompress.Unpack.PPM.SubAllocator'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1005'"
public static readonly int UNIT_SIZE;
public const int FIXED_UNIT_SIZE = 12;
private int subAllocatorSize;
// byte Indx2Units[N_INDEXES], Units2Indx[128], GlueCount;
private int[] indx2Units = new int[N_INDEXES];
private int[] units2Indx = new int[128];
private int glueCount;
// byte *HeapStart,*LoUnit, *HiUnit;
private int heapStart, loUnit, hiUnit;
//UPGRADE_NOTE: Final was removed from the declaration of 'freeList '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
private RarNode[] freeList = new RarNode[N_INDEXES];
// byte *pText, *UnitsStart,*HeapEnd,*FakeUnitsStart;
private int pText, unitsStart, heapEnd, fakeUnitsStart;
private byte[] heap;
private int freeListPos;
private int tempMemBlockPos;
// Temp fields
private RarNode tempRarNode = null;
private RarMemBlock tempRarMemBlock1 = null;
private RarMemBlock tempRarMemBlock2 = null;
private RarMemBlock tempRarMemBlock3 = null;
public SubAllocator()
{
clean();
}
public virtual void clean()
{
subAllocatorSize = 0;
}
private void insertNode(int p, int indx)
{
RarNode temp = tempRarNode;
temp.Address = p;
temp.SetNext(freeList[indx].GetNext());
freeList[indx].SetNext(temp);
}
public virtual void incPText()
{
pText++;
}
private int removeNode(int indx)
{
int retVal = freeList[indx].GetNext();
RarNode temp = tempRarNode;
temp.Address = retVal;
freeList[indx].SetNext(temp.GetNext());
return retVal;
}
private int U2B(int NU)
{
return UNIT_SIZE * NU;
}
/* memblockptr */
private int MBPtr(int BasePtr, int Items)
{
return (BasePtr + U2B(Items));
}
private void splitBlock(int pv, int oldIndx, int newIndx)
{
int i, uDiff = indx2Units[oldIndx] - indx2Units[newIndx];
int p = pv + U2B(indx2Units[newIndx]);
if (indx2Units[i = units2Indx[uDiff - 1]] != uDiff)
{
insertNode(p, --i);
p += U2B(i = indx2Units[i]);
uDiff -= i;
}
insertNode(p, units2Indx[uDiff - 1]);
}
public virtual void stopSubAllocator()
{
if (subAllocatorSize != 0)
{
subAllocatorSize = 0;
//ArrayFactory.BYTES_FACTORY.recycle(heap);
heap = null;
heapStart = 1;
// rarfree(HeapStart);
// Free temp fields
tempRarNode = null;
tempRarMemBlock1 = null;
tempRarMemBlock2 = null;
tempRarMemBlock3 = null;
}
}
public virtual int GetAllocatedMemory()
{
return subAllocatorSize;
}
public virtual bool startSubAllocator(int SASize)
{
int t = SASize;
if (subAllocatorSize == t)
{
return true;
}
stopSubAllocator();
int allocSize = t / FIXED_UNIT_SIZE * UNIT_SIZE + UNIT_SIZE;
// adding space for freelist (needed for poiters)
// 1+ for null pointer
int realAllocSize = 1 + allocSize + 4 * N_INDEXES;
// adding space for an additional memblock
tempMemBlockPos = realAllocSize;
realAllocSize += RarMemBlock.size;
heap = new byte[realAllocSize];
heapStart = 1;
heapEnd = heapStart + allocSize - UNIT_SIZE;
subAllocatorSize = t;
// Bug fixed
freeListPos = heapStart + allocSize;
//UPGRADE_ISSUE: The following fragment of code could not be parsed and was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1156'"
//assert(realAllocSize - tempMemBlockPos == RarMemBlock.size): realAllocSize
//+ + tempMemBlockPos + + RarMemBlock.size;
// Init freeList
for (int i = 0, pos = freeListPos; i < freeList.Length; i++, pos += RarNode.size)
{
freeList[i] = new RarNode(heap);
freeList[i].Address = pos;
}
// Init temp fields
tempRarNode = new RarNode(heap);
tempRarMemBlock1 = new RarMemBlock(heap);
tempRarMemBlock2 = new RarMemBlock(heap);
tempRarMemBlock3 = new RarMemBlock(heap);
return true;
}
private void glueFreeBlocks()
{
RarMemBlock s0 = tempRarMemBlock1;
s0.Address = tempMemBlockPos;
RarMemBlock p = tempRarMemBlock2;
RarMemBlock p1 = tempRarMemBlock3;
int i, k, sz;
if (loUnit != hiUnit)
{
heap[loUnit] = 0;
}
for (i = 0, s0.SetPrev(s0), s0.SetNext(s0); i < N_INDEXES; i++)
{
while (freeList[i].GetNext() != 0)
{
p.Address = removeNode(i); // =(RAR_MEM_BLK*)RemoveNode(i);
p.InsertAt(s0); // p->insertAt(&s0);
p.Stamp = 0xFFFF; // p->Stamp=0xFFFF;
p.SetNU(indx2Units[i]); // p->NU=Indx2Units[i];
}
}
for (p.Address = s0.GetNext(); p.Address != s0.Address; p.Address = p.GetNext())
{
// while ((p1=MBPtr(p,p->NU))->Stamp == 0xFFFF && int(p->NU)+p1->NU
// < 0x10000)
// Bug fixed
p1.Address = MBPtr(p.Address, p.GetNU());
while (p1.Stamp == 0xFFFF && p.GetNU() + p1.GetNU() < 0x10000)
{
p1.Remove();
p.SetNU(p.GetNU() + p1.GetNU()); // ->NU += p1->NU;
p1.Address = MBPtr(p.Address, p.GetNU());
}
}
// while ((p=s0.next) != &s0)
// Bug fixed
p.Address = s0.GetNext();
while (p.Address != s0.Address)
{
for (p.Remove(), sz = p.GetNU(); sz > 128; sz -= 128, p.Address = MBPtr(p.Address, 128))
{
insertNode(p.Address, N_INDEXES - 1);
}
if (indx2Units[i = units2Indx[sz - 1]] != sz)
{
k = sz - indx2Units[--i];
insertNode(MBPtr(p.Address, sz - k), k - 1);
}
insertNode(p.Address, i);
p.Address = s0.GetNext();
}
}
private int allocUnitsRare(int indx)
{
if (glueCount == 0)
{
glueCount = 255;
glueFreeBlocks();
if (freeList[indx].GetNext() != 0)
{
return removeNode(indx);
}
}
int i = indx;
do
{
if (++i == N_INDEXES)
{
glueCount--;
i = U2B(indx2Units[indx]);
int j = FIXED_UNIT_SIZE * indx2Units[indx];
if (fakeUnitsStart - pText > j)
{
fakeUnitsStart -= j;
unitsStart -= i;
return unitsStart;
}
return (0);
}
}
while (freeList[i].GetNext() == 0);
int retVal = removeNode(i);
splitBlock(retVal, i, indx);
return retVal;
}
public virtual int allocUnits(int NU)
{
int indx = units2Indx[NU - 1];
if (freeList[indx].GetNext() != 0)
{
return removeNode(indx);
}
int retVal = loUnit;
loUnit += U2B(indx2Units[indx]);
if (loUnit <= hiUnit)
{
return retVal;
}
loUnit -= U2B(indx2Units[indx]);
return allocUnitsRare(indx);
}
public virtual int allocContext()
{
if (hiUnit != loUnit)
return (hiUnit -= UNIT_SIZE);
if (freeList[0].GetNext() != 0)
{
return removeNode(0);
}
return allocUnitsRare(0);
}
public virtual int expandUnits(int oldPtr, int OldNU)
{
int i0 = units2Indx[OldNU - 1];
int i1 = units2Indx[OldNU - 1 + 1];
if (i0 == i1)
{
return oldPtr;
}
int ptr = allocUnits(OldNU + 1);
if (ptr != 0)
{
// memcpy(ptr,OldPtr,U2B(OldNU));
Array.Copy(heap, oldPtr, heap, ptr, U2B(OldNU));
insertNode(oldPtr, i0);
}
return ptr;
}
public virtual int shrinkUnits(int oldPtr, int oldNU, int newNU)
{
// System.out.println("SubAllocator.shrinkUnits(" + OldPtr + ", " +
// OldNU + ", " + NewNU + ")");
int i0 = units2Indx[oldNU - 1];
int i1 = units2Indx[newNU - 1];
if (i0 == i1)
{
return oldPtr;
}
if (freeList[i1].GetNext() != 0)
{
int ptr = removeNode(i1);
// memcpy(ptr,OldPtr,U2B(NewNU));
// for (int i = 0; i < U2B(NewNU); i++) {
// heap[ptr + i] = heap[OldPtr + i];
// }
Array.Copy(heap, oldPtr, heap, ptr, U2B(newNU));
insertNode(oldPtr, i0);
return ptr;
}
else
{
splitBlock(oldPtr, i0, i1);
return oldPtr;
}
}
public virtual void freeUnits(int ptr, int OldNU)
{
insertNode(ptr, units2Indx[OldNU - 1]);
}
public virtual void decPText(int dPText)
{
PText = PText - dPText;
}
public virtual void initSubAllocator()
{
int i, k;
Utility.Fill(heap, freeListPos, freeListPos + sizeOfFreeList(), (byte)0);
pText = heapStart;
int size2 = FIXED_UNIT_SIZE * (subAllocatorSize / 8 / FIXED_UNIT_SIZE * 7);
int realSize2 = size2 / FIXED_UNIT_SIZE * UNIT_SIZE;
int size1 = subAllocatorSize - size2;
int realSize1 = size1 / FIXED_UNIT_SIZE * UNIT_SIZE + size1 % FIXED_UNIT_SIZE;
hiUnit = heapStart + subAllocatorSize;
loUnit = unitsStart = heapStart + realSize1;
fakeUnitsStart = heapStart + size1;
hiUnit = loUnit + realSize2;
for (i = 0, k = 1; i < N1; i++, k += 1)
{
indx2Units[i] = k & 0xff;
}
for (k++; i < N1 + N2; i++, k += 2)
{
indx2Units[i] = k & 0xff;
}
for (k++; i < N1 + N2 + N3; i++, k += 3)
{
indx2Units[i] = k & 0xff;
}
for (k++; i < (N1 + N2 + N3 + N4); i++, k += 4)
{
indx2Units[i] = k & 0xff;
}
for (glueCount = 0, k = 0, i = 0; k < 128; k++)
{
i += ((indx2Units[i] < (k + 1)) ? 1 : 0);
units2Indx[k] = i & 0xff;
}
}
private int sizeOfFreeList()
{
return freeList.Length * RarNode.size;
}
// Debug
// public void dumpHeap() {
// File file = new File("P:\\test\\heapdumpj");
// OutputStream out = null;
// try {
// out = new FileOutputStream(file);
// out.write(heap, heapStart, heapEnd - heapStart);
// out.flush();
// System.out.println("Heap dumped to " + file.getAbsolutePath());
// }
// catch (IOException e) {
// e.printStackTrace();
// }
// finally {
// FileUtil.close(out);
// }
// }
// Debug
public override System.String ToString()
{
StringBuilder buffer = new StringBuilder();
buffer.Append("SubAllocator[");
buffer.Append("\n subAllocatorSize=");
buffer.Append(subAllocatorSize);
buffer.Append("\n glueCount=");
buffer.Append(glueCount);
buffer.Append("\n heapStart=");
buffer.Append(heapStart);
buffer.Append("\n loUnit=");
buffer.Append(loUnit);
buffer.Append("\n hiUnit=");
buffer.Append(hiUnit);
buffer.Append("\n pText=");
buffer.Append(pText);
buffer.Append("\n unitsStart=");
buffer.Append(unitsStart);
buffer.Append("\n]");
return buffer.ToString();
}
static SubAllocator()
{
UNIT_SIZE = System.Math.Max(PPMContext.size, RarMemBlock.size);
}
}
}

View File

@@ -1,457 +0,0 @@
#region Using
#endregion
namespace Compress.SevenZip.Compress.PPmd.I1
{
/// Allocate a single, large array and then provide sections of this array to callers. Callers are provided with
/// instances of <see cref="Pointer"/> (which simply contain a single address value, representing a location
/// in the large array). Callers can then cast <see cref="Pointer"/> to one of the following structures (all
/// of which also simply contain a single address value):
internal class Allocator
{
private const uint UnitSize = 12;
private const uint LocalOffset = 4; // reserve the first four bytes for Pointer.Zero
private const uint NodeOffset = LocalOffset + MemoryNode.Size; // reserve space for a single memory node
private const uint HeapOffset = NodeOffset + IndexCount * MemoryNode.Size; // reserve space for the array of memory nodes
private const uint N1 = 4;
private const uint N2 = 4;
private const uint N3 = 4;
private const uint N4 = (128 + 3 - 1 * N1 - 2 * N2 - 3 * N3) / 4;
private const uint IndexCount = N1 + N2 + N3 + N4;
private static readonly byte[] indexToUnits;
private static readonly byte[] unitsToIndex;
public uint AllocatorSize;
public uint GlueCount;
public Pointer BaseUnit;
public Pointer LowUnit;
public Pointer HighUnit;
public Pointer Text;
public Pointer Heap;
public MemoryNode[] MemoryNodes;
public byte[] Memory;
/// <summary>
/// Initializes static read-only arrays used by the <see cref="Allocator"/>.
/// </summary>
static Allocator()
{
// Construct the static index to units lookup array. It will contain the following values.
//
// 1 2 3 4 6 8 10 12 15 18 21 24 28 32 36 40 44 48 52 56 60 64 68 72 76 80 84 88 92 96 100 104 108
// 112 116 120 124 128
uint index;
uint unitCount;
indexToUnits = new byte[IndexCount];
for (index = 0, unitCount = 1; index < N1; index++, unitCount += 1)
indexToUnits[index] = (byte)unitCount;
for (unitCount++; index < N1 + N2; index++, unitCount += 2)
indexToUnits[index] = (byte)unitCount;
for (unitCount++; index < N1 + N2 + N3; index++, unitCount += 3)
indexToUnits[index] = (byte)unitCount;
for (unitCount++; index < N1 + N2 + N3 + N4; index++, unitCount += 4)
indexToUnits[index] = (byte)unitCount;
// Construct the static units to index lookup array. It will contain the following values.
//
// 00 01 02 03 04 04 05 05 06 06 07 07 08 08 08 09 09 09 10 10 10 11 11 11 12 12 12 12 13 13 13 13
// 14 14 14 14 15 15 15 15 16 16 16 16 17 17 17 17 18 18 18 18 19 19 19 19 20 20 20 20 21 21 21 21
// 22 22 22 22 23 23 23 23 24 24 24 24 25 25 25 25 26 26 26 26 27 27 27 27 28 28 28 28 29 29 29 29
// 30 30 30 30 31 31 31 31 32 32 32 32 33 33 33 33 34 34 34 34 35 35 35 35 36 36 36 36 37 37 37 37
unitsToIndex = new byte[128];
for (unitCount = index = 0; unitCount < 128; unitCount++)
{
index += (uint)((indexToUnits[index] < unitCount + 1) ? 1 : 0);
unitsToIndex[unitCount] = (byte)index;
}
}
#region Public Methods
public Allocator()
{
MemoryNodes = new MemoryNode[IndexCount];
}
/// <summary>
/// Initialize or reset the memory allocator (so that the single, large array can be re-used without destroying
/// and re-creating it).
/// </summary>
public void Initialize()
{
for (int index = 0; index < IndexCount; index++)
{
MemoryNodes[index] = new MemoryNode((uint)(NodeOffset + index * MemoryNode.Size), Memory);
MemoryNodes[index].Stamp = 0;
MemoryNodes[index].Next = MemoryNode.Zero;
MemoryNodes[index].UnitCount = 0;
}
Text = Heap;
uint difference = UnitSize * (AllocatorSize / 8 / UnitSize * 7);
HighUnit = Heap + AllocatorSize;
LowUnit = HighUnit - difference;
BaseUnit = HighUnit - difference;
GlueCount = 0;
}
/// <summary>
/// Start the allocator (create a single, large array of bytes).
/// </summary>
/// <remarks>
/// Note that .NET will create that array on the large object heap (because it is so large).
/// </remarks>
/// <param name="allocatorSize"></param>
public void Start(int allocatorSize)
{
uint size = (uint)allocatorSize;
if (AllocatorSize != size)
{
Stop();
Memory = new byte[HeapOffset + size]; // the single, large array of bytes
Heap = new Pointer(HeapOffset, Memory); // reserve bytes in the range 0 .. HeapOffset - 1
AllocatorSize = size;
}
}
/// <summary>
/// Stop the allocator (free the single, large array of bytes). This can safely be called multiple times (without
/// intervening calls to <see cref="Start"/>).
/// </summary>
/// <remarks>
/// Because the array is on the large object heap it may not be freed immediately.
/// </remarks>
public void Stop()
{
if (AllocatorSize != 0)
{
AllocatorSize = 0;
Memory = null;
Heap = Pointer.Zero;
}
}
/// <summary>
/// Determine how much memory (from the single, large array) is currenly in use.
/// </summary>
/// <returns></returns>
public uint GetMemoryUsed()
{
uint memoryUsed = AllocatorSize - (HighUnit - LowUnit) - (BaseUnit - Text);
for (uint index = 0; index < IndexCount; index++)
memoryUsed -= UnitSize * indexToUnits[index] * MemoryNodes[index].Stamp;
return memoryUsed;
}
/// <summary>
/// Allocate a given number of units from the single, large array. Each unit is <see cref="UnitSize"/> bytes
/// in size.
/// </summary>
/// <param name="unitCount"></param>
/// <returns></returns>
public Pointer AllocateUnits(uint unitCount)
{
uint index = unitsToIndex[unitCount - 1];
if (MemoryNodes[index].Available)
return MemoryNodes[index].Remove();
Pointer allocatedBlock = LowUnit;
LowUnit += indexToUnits[index] * UnitSize;
if (LowUnit <= HighUnit)
return allocatedBlock;
LowUnit -= indexToUnits[index] * UnitSize;
return AllocateUnitsRare(index);
}
/// <summary>
/// Allocate enough space for a PpmContext instance in the single, large array.
/// </summary>
/// <returns></returns>
public Pointer AllocateContext()
{
if (HighUnit != LowUnit)
return (HighUnit -= UnitSize);
else if (MemoryNodes[0].Available)
return MemoryNodes[0].Remove();
else
return AllocateUnitsRare(0);
}
/// <summary>
/// Increase the size of an existing allocation (represented by a <see cref="Pointer"/>).
/// </summary>
/// <param name="oldPointer"></param>
/// <param name="oldUnitCount"></param>
/// <returns></returns>
public Pointer ExpandUnits(Pointer oldPointer, uint oldUnitCount)
{
uint oldIndex = unitsToIndex[oldUnitCount - 1];
uint newIndex = unitsToIndex[oldUnitCount];
if (oldIndex == newIndex)
return oldPointer;
Pointer pointer = AllocateUnits(oldUnitCount + 1);
if (pointer != Pointer.Zero)
{
CopyUnits(pointer, oldPointer, oldUnitCount);
MemoryNodes[oldIndex].Insert(oldPointer, oldUnitCount);
}
return pointer;
}
/// <summary>
/// Decrease the size of an existing allocation (represented by a <see cref="Pointer"/>).
/// </summary>
/// <param name="oldPointer"></param>
/// <param name="oldUnitCount"></param>
/// <param name="newUnitCount"></param>
/// <returns></returns>
public Pointer ShrinkUnits(Pointer oldPointer, uint oldUnitCount, uint newUnitCount)
{
uint oldIndex = unitsToIndex[oldUnitCount - 1];
uint newIndex = unitsToIndex[newUnitCount - 1];
if (oldIndex == newIndex)
return oldPointer;
if (MemoryNodes[newIndex].Available)
{
Pointer pointer = MemoryNodes[newIndex].Remove();
CopyUnits(pointer, oldPointer, newUnitCount);
MemoryNodes[oldIndex].Insert(oldPointer, indexToUnits[oldIndex]);
return pointer;
}
else
{
SplitBlock(oldPointer, oldIndex, newIndex);
return oldPointer;
}
}
/// <summary>
/// Free previously allocated space (the location and amount of space to free must be specified by using
/// a <see cref="Pointer"/> to indicate the location and a number of units to indicate the amount).
/// </summary>
/// <param name="pointer"></param>
/// <param name="unitCount"></param>
public void FreeUnits(Pointer pointer, uint unitCount)
{
uint index = unitsToIndex[unitCount - 1];
MemoryNodes[index].Insert(pointer, indexToUnits[index]);
}
public void SpecialFreeUnits(Pointer pointer)
{
if (pointer != BaseUnit)
{
MemoryNodes[0].Insert(pointer, 1);
}
else
{
MemoryNode memoryNode = pointer;
memoryNode.Stamp = uint.MaxValue;
BaseUnit += UnitSize;
}
}
public Pointer MoveUnitsUp(Pointer oldPointer, uint unitCount)
{
uint index = unitsToIndex[unitCount - 1];
if (oldPointer > BaseUnit + 16 * 1024 || oldPointer > MemoryNodes[index].Next)
return oldPointer;
Pointer pointer = MemoryNodes[index].Remove();
CopyUnits(pointer, oldPointer, unitCount);
unitCount = indexToUnits[index];
if (oldPointer != BaseUnit)
MemoryNodes[index].Insert(oldPointer, unitCount);
else
BaseUnit += unitCount * UnitSize;
return pointer;
}
/// <summary>
/// Expand the space allocated (in the single, large array) for the bytes of the data (ie. the "text") that is
/// being encoded or decoded.
/// </summary>
public void ExpandText()
{
MemoryNode memoryNode;
uint[] counts = new uint[IndexCount];
while ((memoryNode = BaseUnit).Stamp == uint.MaxValue)
{
BaseUnit = memoryNode + memoryNode.UnitCount;
counts[unitsToIndex[memoryNode.UnitCount - 1]]++;
memoryNode.Stamp = 0;
}
for (uint index = 0; index < IndexCount; index++)
{
for (memoryNode = MemoryNodes[index]; counts[index] != 0; memoryNode = memoryNode.Next)
{
while (memoryNode.Next.Stamp == 0)
{
memoryNode.Unlink();
MemoryNodes[index].Stamp--;
if (--counts[index] == 0)
break;
}
}
}
}
#endregion
#region Private Methods
private Pointer AllocateUnitsRare(uint index)
{
if (GlueCount == 0)
{
GlueFreeBlocks();
if (MemoryNodes[index].Available)
return MemoryNodes[index].Remove();
}
uint oldIndex = index;
do
{
if (++oldIndex == IndexCount)
{
GlueCount--;
oldIndex = indexToUnits[index] * UnitSize;
return (BaseUnit - Text > oldIndex) ? (BaseUnit -= oldIndex) : Pointer.Zero;
}
} while (!MemoryNodes[oldIndex].Available);
Pointer allocatedBlock = MemoryNodes[oldIndex].Remove();
SplitBlock(allocatedBlock, oldIndex, index);
return allocatedBlock;
}
private void SplitBlock(Pointer pointer, uint oldIndex, uint newIndex)
{
uint unitCountDifference = (uint)(indexToUnits[oldIndex] - indexToUnits[newIndex]);
Pointer newPointer = pointer + indexToUnits[newIndex] * UnitSize;
uint index = unitsToIndex[unitCountDifference - 1];
if (indexToUnits[index] != unitCountDifference)
{
uint unitCount = indexToUnits[--index];
MemoryNodes[index].Insert(newPointer, unitCount);
newPointer += unitCount * UnitSize;
unitCountDifference -= unitCount;
}
MemoryNodes[unitsToIndex[unitCountDifference - 1]].Insert(newPointer, unitCountDifference);
}
private void GlueFreeBlocks()
{
MemoryNode memoryNode = new MemoryNode(LocalOffset, Memory);
memoryNode.Stamp = 0;
memoryNode.Next = MemoryNode.Zero;
memoryNode.UnitCount = 0;
MemoryNode memoryNode0;
MemoryNode memoryNode1;
MemoryNode memoryNode2;
if (LowUnit != HighUnit)
LowUnit[0] = 0;
// Find all unused memory nodes.
memoryNode1 = memoryNode;
for (uint index = 0; index < IndexCount; index++)
{
while (MemoryNodes[index].Available)
{
memoryNode0 = MemoryNodes[index].Remove();
if (memoryNode0.UnitCount != 0)
{
while ((memoryNode2 = memoryNode0 + memoryNode0.UnitCount).Stamp == uint.MaxValue)
{
memoryNode0.UnitCount = memoryNode0.UnitCount + memoryNode2.UnitCount;
memoryNode2.UnitCount = 0;
}
memoryNode1.Link(memoryNode0);
memoryNode1 = memoryNode0;
}
}
}
// Coalesce the memory represented by the unused memory nodes.
while (memoryNode.Available)
{
memoryNode0 = memoryNode.Remove();
uint unitCount = memoryNode0.UnitCount;
if (unitCount != 0)
{
for (; unitCount > 128; unitCount -= 128, memoryNode0 += 128)
MemoryNodes[IndexCount - 1].Insert(memoryNode0, 128);
uint index = unitsToIndex[unitCount - 1];
if (indexToUnits[index] != unitCount)
{
uint unitCountDifference = unitCount - indexToUnits[--index];
MemoryNodes[unitCountDifference - 1].Insert(memoryNode0 + (unitCount - unitCountDifference), unitCountDifference);
}
MemoryNodes[index].Insert(memoryNode0, indexToUnits[index]);
}
}
GlueCount = 1 << 13;
}
private void CopyUnits(Pointer target, Pointer source, uint unitCount)
{
do
{
target[0] = source[0];
target[1] = source[1];
target[2] = source[2];
target[3] = source[3];
target[4] = source[4];
target[5] = source[5];
target[6] = source[6];
target[7] = source[7];
target[8] = source[8];
target[9] = source[9];
target[10] = source[10];
target[11] = source[11];
target += UnitSize;
source += UnitSize;
} while (--unitCount != 0);
}
#endregion
}
}

View File

@@ -1,100 +0,0 @@
#region Using
using System.IO;
#endregion
namespace Compress.SevenZip.Compress.PPmd.I1
{
/// <summary>
/// A simple range coder.
/// </summary>
/// <remarks>
/// Note that in most cases fields are used rather than properties for performance reasons (for example,
/// <see cref="Scale"/> is a field rather than a property).
/// </remarks>
internal class Coder
{
private const uint RangeTop = 1 << 24;
private const uint RangeBottom = 1 << 15;
private uint low;
private uint code;
private uint range;
public uint LowCount;
public uint HighCount;
public uint Scale;
public void RangeEncoderInitialize()
{
low = 0;
range = uint.MaxValue;
}
public void RangeEncoderNormalize(Stream stream)
{
while ((low ^ (low + range)) < RangeTop || range < RangeBottom && ((range = (uint)-low & (RangeBottom - 1)) != 0 || true))
{
stream.WriteByte((byte)(low >> 24));
range <<= 8;
low <<= 8;
}
}
public void RangeEncodeSymbol()
{
low += LowCount * (range /= Scale);
range *= HighCount - LowCount;
}
public void RangeShiftEncodeSymbol(int rangeShift)
{
low += LowCount * (range >>= rangeShift);
range *= HighCount - LowCount;
}
public void RangeEncoderFlush(Stream stream)
{
for (uint index = 0; index < 4; index++)
{
stream.WriteByte((byte)(low >> 24));
low <<= 8;
}
}
public void RangeDecoderInitialize(Stream stream)
{
low = 0;
code = 0;
range = uint.MaxValue;
for (uint index = 0; index < 4; index++)
code = (code << 8) | (byte)stream.ReadByte();
}
public void RangeDecoderNormalize(Stream stream)
{
while ((low ^ (low + range)) < RangeTop || range < RangeBottom && ((range = (uint)-low & (RangeBottom - 1)) != 0 || true))
{
code = (code << 8) | (byte)stream.ReadByte();
range <<= 8;
low <<= 8;
}
}
public uint RangeGetCurrentCount()
{
return (code - low) / (range /= Scale);
}
public uint RangeGetCurrentShiftCount(int rangeShift)
{
return (code - low) / (range >>= rangeShift);
}
public void RangeRemoveSubrange()
{
low += range * LowCount;
range *= HighCount - LowCount;
}
}
}

View File

@@ -1,246 +0,0 @@
#region Using
#endregion
namespace Compress.SevenZip.Compress.PPmd.I1
{
/// <summary>
/// A structure containing a single address. The address represents a location in the <see cref="Memory"/>
/// array. That location in the <see cref="Memory"/> array contains information itself describing a section
/// of the <see cref="Memory"/> array (ie. a block of memory).
/// </summary>
/// <remarks>
/// <para>
/// This must be a structure rather than a class because several places in the associated code assume that
/// <see cref="MemoryNode"/> is a value type (meaning that assignment creates a completely new copy of
/// the instance rather than just copying a reference to the same instance).
/// </para>
/// <para>
/// MemoryNode
/// 4 Stamp
/// 4 Next
/// 4 UnitCount
/// </para>
/// <para>
/// Note that <see cref="Address"/> is a field rather than a property for performance reasons.
/// </para>
/// </remarks>
internal struct MemoryNode
{
public uint Address;
public byte[] Memory;
public static readonly MemoryNode Zero = new MemoryNode(0, null);
public const int Size = 12;
/// <summary>
/// Initializes a new instance of the <see cref="MemoryNode"/> structure.
/// </summary>
public MemoryNode(uint address, byte[] memory)
{
Address = address;
Memory = memory;
}
/// <summary>
/// Gets or sets the stamp.
/// </summary>
public uint Stamp
{
get { return ((uint)Memory[Address]) | ((uint)Memory[Address + 1]) << 8 | ((uint)Memory[Address + 2]) << 16 | ((uint)Memory[Address + 3]) << 24; }
set
{
Memory[Address] = (byte)value;
Memory[Address + 1] = (byte)(value >> 8);
Memory[Address + 2] = (byte)(value >> 16);
Memory[Address + 3] = (byte)(value >> 24);
}
}
/// <summary>
/// Gets or sets the next memory node.
/// </summary>
public MemoryNode Next
{
get { return new MemoryNode(((uint)Memory[Address + 4]) | ((uint)Memory[Address + 5]) << 8 | ((uint)Memory[Address + 6]) << 16 | ((uint)Memory[Address + 7]) << 24, Memory); }
set
{
Memory[Address + 4] = (byte)value.Address;
Memory[Address + 5] = (byte)(value.Address >> 8);
Memory[Address + 6] = (byte)(value.Address >> 16);
Memory[Address + 7] = (byte)(value.Address >> 24);
}
}
/// <summary>
/// Gets or sets the unit count.
/// </summary>
public uint UnitCount
{
get { return ((uint)Memory[Address + 8]) | ((uint)Memory[Address + 9]) << 8 | ((uint)Memory[Address + 10]) << 16 | ((uint)Memory[Address + 11]) << 24; }
set
{
Memory[Address + 8] = (byte)value;
Memory[Address + 9] = (byte)(value >> 8);
Memory[Address + 10] = (byte)(value >> 16);
Memory[Address + 11] = (byte)(value >> 24);
}
}
/// <summary>
/// Gets whether there is a next memory node available.
/// </summary>
public bool Available
{
get { return Next.Address != 0; }
}
/// <summary>
/// Link in the provided memory node.
/// </summary>
/// <param name="memoryNode"></param>
public void Link(MemoryNode memoryNode)
{
memoryNode.Next = Next;
Next = memoryNode;
}
/// <summary>
/// Unlink this memory node.
/// </summary>
public void Unlink()
{
Next = Next.Next;
}
/// <summary>
/// Insert the memory node into the linked list.
/// </summary>
/// <param name="memoryNode"></param>
/// <param name="unitCount"></param>
public void Insert(MemoryNode memoryNode, uint unitCount)
{
Link(memoryNode);
memoryNode.Stamp = uint.MaxValue;
memoryNode.UnitCount = unitCount;
Stamp++;
}
/// <summary>
/// Remove this memory node from the linked list.
/// </summary>
/// <returns></returns>
public MemoryNode Remove()
{
MemoryNode next = Next;
Unlink();
Stamp--;
return next;
}
/// <summary>
/// Allow a pointer to be implicitly converted to a memory node.
/// </summary>
/// <param name="pointer"></param>
/// <returns></returns>
public static implicit operator MemoryNode(Pointer pointer)
{
return new MemoryNode(pointer.Address, pointer.Memory);
}
/// <summary>
/// Allow pointer-like addition on a memory node.
/// </summary>
/// <param name="memoryNode"></param>
/// <param name="offset"></param>
/// <returns></returns>
public static MemoryNode operator +(MemoryNode memoryNode, int offset)
{
memoryNode.Address = (uint)(memoryNode.Address + offset * Size);
return memoryNode;
}
/// <summary>
/// Allow pointer-like addition on a memory node.
/// </summary>
/// <param name="memoryNode"></param>
/// <param name="offset"></param>
/// <returns></returns>
public static MemoryNode operator +(MemoryNode memoryNode, uint offset)
{
memoryNode.Address += offset * Size;
return memoryNode;
}
/// <summary>
/// Allow pointer-like subtraction on a memory node.
/// </summary>
/// <param name="memoryNode"></param>
/// <param name="offset"></param>
/// <returns></returns>
public static MemoryNode operator -(MemoryNode memoryNode, int offset)
{
memoryNode.Address = (uint)(memoryNode.Address - offset * Size);
return memoryNode;
}
/// <summary>
/// Allow pointer-like subtraction on a memory node.
/// </summary>
/// <param name="memoryNode"></param>
/// <param name="offset"></param>
/// <returns></returns>
public static MemoryNode operator -(MemoryNode memoryNode, uint offset)
{
memoryNode.Address -= offset * Size;
return memoryNode;
}
/// <summary>
/// Compare two memory nodes.
/// </summary>
/// <param name="memoryNode1"></param>
/// <param name="memoryNode2"></param>
/// <returns></returns>
public static bool operator ==(MemoryNode memoryNode1, MemoryNode memoryNode2)
{
return memoryNode1.Address == memoryNode2.Address;
}
/// <summary>
/// Compare two memory nodes.
/// </summary>
/// <param name="memoryNode1"></param>
/// <param name="memoryNode2"></param>
/// <returns></returns>
public static bool operator !=(MemoryNode memoryNode1, MemoryNode memoryNode2)
{
return memoryNode1.Address != memoryNode2.Address;
}
/// <summary>
/// Indicates whether this instance and a specified object are equal.
/// </summary>
/// <returns>true if obj and this instance are the same type and represent the same value; otherwise, false.</returns>
/// <param name="obj">Another object to compare to.</param>
public override bool Equals(object obj)
{
if (obj is MemoryNode)
{
MemoryNode memoryNode = (MemoryNode)obj;
return memoryNode.Address == Address;
}
return base.Equals(obj);
}
/// <summary>
/// Returns the hash code for this instance.
/// </summary>
/// <returns>A 32-bit signed integer that is the hash code for this instance.</returns>
public override int GetHashCode()
{
return Address.GetHashCode();
}
}
}

View File

@@ -1,819 +0,0 @@
#region Using
using System;
using System.IO;
#endregion
// This is a port of Dmitry Shkarin's PPMd Variant I Revision 1.
// Ported by Michael Bone (mjbone03@yahoo.com.au).
namespace Compress.SevenZip.Compress.PPmd.I1
{
/// <summary>
/// The model.
/// </summary>
internal partial class Model
{
public const uint Signature = 0x84acaf8fU;
public const char Variant = 'I';
public const int MaximumOrder = 16; // maximum allowed model order
private const byte UpperFrequency = 5;
private const byte IntervalBitCount = 7;
private const byte PeriodBitCount = 7;
private const byte TotalBitCount = IntervalBitCount + PeriodBitCount;
private const uint Interval = 1 << IntervalBitCount;
private const uint BinaryScale = 1 << TotalBitCount;
private const uint MaximumFrequency = 124;
private const uint OrderBound = 9;
private See2Context[,] see2Contexts;
private See2Context emptySee2Context;
private PpmContext maximumContext;
private ushort[,] binarySummary = new ushort[25, 64]; // binary SEE-contexts
private byte[] numberStatisticsToBinarySummaryIndex = new byte[256];
private byte[] probabilities = new byte[260];
private byte[] characterMask = new byte[256];
private byte escapeCount;
private int modelOrder;
private int orderFall;
private int initialEscape;
private int initialRunLength;
private int runLength;
private byte previousSuccess;
private byte numberMasked;
private ModelRestorationMethod method;
private PpmState foundState; // found next state transition
private Allocator Allocator;
private Coder Coder;
private PpmContext minimumContext;
private byte numberStatistics;
private PpmState[] decodeStates = new PpmState[256];
private static readonly ushort[] InitialBinaryEscapes = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051 };
private static readonly byte[] ExponentialEscapes = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
#region Public Methods
public Model()
{
// Construct the conversion table for number statistics. Initially it will contain the following values.
//
// 0 2 4 4 4 4 4 4 4 4 4 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6
// 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6
// 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6
// 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6
// 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6
// 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6
// 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6
// 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6
numberStatisticsToBinarySummaryIndex[0] = 2 * 0;
numberStatisticsToBinarySummaryIndex[1] = 2 * 1;
for (int index = 2; index < 11; index++)
numberStatisticsToBinarySummaryIndex[index] = 2 * 2;
for (int index = 11; index < 256; index++)
numberStatisticsToBinarySummaryIndex[index] = 2 * 3;
// Construct the probability table. Initially it will contain the following values (depending on the value of
// the upper frequency).
//
// 00 01 02 03 04 05 06 06 07 07 07 08 08 08 08 09 09 09 09 09 10 10 10 10 10 10 11 11 11 11 11 11
// 11 12 12 12 12 12 12 12 12 13 13 13 13 13 13 13 13 13 14 14 14 14 14 14 14 14 14 14 15 15 15 15
// 15 15 15 15 15 15 15 16 16 16 16 16 16 16 16 16 16 16 16 17 17 17 17 17 17 17 17 17 17 17 17 17
// 18 18 18 18 18 18 18 18 18 18 18 18 18 18 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 20 20 20
// 20 20 20 20 20 20 20 20 20 20 20 20 20 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 22 22
// 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23
// 23 23 23 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 25 25 25 25 25 25 25 25 25
// 25 25 25 25 25 25 25 25 25 25 25 25 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26
// 26 26 27 27
uint count = 1;
uint step = 1;
uint probability = UpperFrequency;
for (int index = 0; index < UpperFrequency; index++)
probabilities[index] = (byte)index;
for (int index = UpperFrequency; index < 260; index++)
{
probabilities[index] = (byte)probability;
count--;
if (count == 0)
{
step++;
count = step;
probability++;
}
}
// Create the context array.
see2Contexts = new See2Context[24, 32];
for (int index1 = 0; index1 < 24; index1++)
for (int index2 = 0; index2 < 32; index2++)
see2Contexts[index1, index2] = new See2Context();
// Set the signature (identifying the algorithm).
emptySee2Context = new See2Context();
emptySee2Context.Summary = (ushort)(Signature & 0x0000ffff);
emptySee2Context.Shift = (byte)((Signature >> 16) & 0x000000ff);
emptySee2Context.Count = (byte)(Signature >> 24);
}
/// <summary>
/// Encode (ie. compress) a given source stream, writing the encoded result to the target stream.
/// </summary>
public void Encode(Stream target, Stream source, PpmdProperties properties)
{
if (target == null)
throw new ArgumentNullException("target");
if (source == null)
throw new ArgumentNullException("source");
EncodeStart(properties);
EncodeBlock(target, source, true);
}
internal Coder EncodeStart(PpmdProperties properties)
{
Allocator = properties.Allocator;
Coder = new Coder();
Coder.RangeEncoderInitialize();
StartModel(properties.ModelOrder, properties.ModelRestorationMethod);
return Coder;
}
internal void EncodeBlock(Stream target, Stream source, bool final)
{
while (true)
{
minimumContext = maximumContext;
numberStatistics = minimumContext.NumberStatistics;
int c = source.ReadByte();
if (c < 0 && !final)
return;
if (numberStatistics != 0)
{
EncodeSymbol1(c, minimumContext);
Coder.RangeEncodeSymbol();
}
else
{
EncodeBinarySymbol(c, minimumContext);
Coder.RangeShiftEncodeSymbol(TotalBitCount);
}
while (foundState == PpmState.Zero)
{
Coder.RangeEncoderNormalize(target);
do
{
orderFall++;
minimumContext = minimumContext.Suffix;
if (minimumContext == PpmContext.Zero)
goto StopEncoding;
} while (minimumContext.NumberStatistics == numberMasked);
EncodeSymbol2(c, minimumContext);
Coder.RangeEncodeSymbol();
}
if (orderFall == 0 && (Pointer)foundState.Successor >= Allocator.BaseUnit)
{
maximumContext = foundState.Successor;
}
else
{
UpdateModel(minimumContext);
if (escapeCount == 0)
ClearMask();
}
Coder.RangeEncoderNormalize(target);
}
StopEncoding:
Coder.RangeEncoderFlush(target);
}
/// <summary>
/// Dencode (ie. decompress) a given source stream, writing the decoded result to the target stream.
/// </summary>
public void Decode(Stream target, Stream source, PpmdProperties properties)
{
if (target == null)
throw new ArgumentNullException("target");
if (source == null)
throw new ArgumentNullException("source");
DecodeStart(source, properties);
byte[] buffer = new byte[65536];
int read;
while ((read = DecodeBlock(source, buffer, 0, buffer.Length)) != 0)
target.Write(buffer, 0, read);
return;
}
internal Coder DecodeStart(Stream source, PpmdProperties properties)
{
Allocator = properties.Allocator;
Coder = new Coder();
Coder.RangeDecoderInitialize(source);
StartModel(properties.ModelOrder, properties.ModelRestorationMethod);
minimumContext = maximumContext;
numberStatistics = minimumContext.NumberStatistics;
return Coder;
}
internal int DecodeBlock(Stream source, byte[] buffer, int offset, int count)
{
if (minimumContext == PpmContext.Zero)
return 0;
int total = 0;
while (total < count)
{
if (numberStatistics != 0)
DecodeSymbol1(minimumContext);
else
DecodeBinarySymbol(minimumContext);
Coder.RangeRemoveSubrange();
while (foundState == PpmState.Zero)
{
Coder.RangeDecoderNormalize(source);
do
{
orderFall++;
minimumContext = minimumContext.Suffix;
if (minimumContext == PpmContext.Zero)
goto StopDecoding;
} while (minimumContext.NumberStatistics == numberMasked);
DecodeSymbol2(minimumContext);
Coder.RangeRemoveSubrange();
}
buffer[offset] = foundState.Symbol;
offset++;
total++;
if (orderFall == 0 && (Pointer)foundState.Successor >= Allocator.BaseUnit)
{
maximumContext = foundState.Successor;
}
else
{
UpdateModel(minimumContext);
if (escapeCount == 0)
ClearMask();
}
minimumContext = maximumContext;
numberStatistics = minimumContext.NumberStatistics;
Coder.RangeDecoderNormalize(source);
}
StopDecoding:
return total;
}
#endregion
#region Private Methods
/// <summary>
/// Initialise the model (unless the model order is set to 1 in which case the model should be cleared so that
/// the statistics are carried over, allowing "solid" mode compression).
/// </summary>
private void StartModel(int modelOrder, ModelRestorationMethod modelRestorationMethod)
{
Array.Clear(characterMask, 0, characterMask.Length);
escapeCount = 1;
// Compress in "solid" mode if the model order value is set to 1 (this will examine the current PPM context
// structures to determine the value of orderFall).
if (modelOrder < 2)
{
orderFall = this.modelOrder;
for (PpmContext context = maximumContext; context.Suffix != PpmContext.Zero; context = context.Suffix)
orderFall--;
return;
}
this.modelOrder = modelOrder;
orderFall = modelOrder;
method = modelRestorationMethod;
Allocator.Initialize();
initialRunLength = -((modelOrder < 12) ? modelOrder : 12) - 1;
runLength = initialRunLength;
// Allocate the context structure.
maximumContext = Allocator.AllocateContext();
maximumContext.Suffix = PpmContext.Zero;
maximumContext.NumberStatistics = 255;
maximumContext.SummaryFrequency = (ushort)(maximumContext.NumberStatistics + 2);
maximumContext.Statistics = Allocator.AllocateUnits(256 / 2); // allocates enough space for 256 PPM states (each is 6 bytes)
previousSuccess = 0;
for (int index = 0; index < 256; index++)
{
PpmState state = maximumContext.Statistics[index];
state.Symbol = (byte)index;
state.Frequency = 1;
state.Successor = PpmContext.Zero;
}
uint probability = 0;
for (int index1 = 0; probability < 25; probability++)
{
while (probabilities[index1] == probability)
index1++;
for (int index2 = 0; index2 < 8; index2++)
binarySummary[probability, index2] = (ushort)(BinaryScale - InitialBinaryEscapes[index2] / (index1 + 1));
for (int index2 = 8; index2 < 64; index2 += 8)
for (int index3 = 0; index3 < 8; index3++)
binarySummary[probability, index2 + index3] = binarySummary[probability, index3];
}
probability = 0;
for (uint index1 = 0; probability < 24; probability++)
{
while (probabilities[index1 + 3] == probability + 3)
index1++;
for (int index2 = 0; index2 < 32; index2++)
see2Contexts[probability, index2].Initialize(2 * index1 + 5);
}
}
private void UpdateModel(PpmContext minimumContext)
{
PpmState state = PpmState.Zero;
PpmContext Successor;
PpmContext currentContext = maximumContext;
uint numberStatistics;
uint ns1;
uint cf;
uint sf;
uint s0;
uint foundStateFrequency = foundState.Frequency;
byte foundStateSymbol = foundState.Symbol;
byte symbol;
byte flag;
PpmContext foundStateSuccessor = foundState.Successor;
PpmContext context = minimumContext.Suffix;
if ((foundStateFrequency < MaximumFrequency / 4) && (context != PpmContext.Zero))
{
if (context.NumberStatistics != 0)
{
state = context.Statistics;
if (state.Symbol != foundStateSymbol)
{
do
{
symbol = state[1].Symbol;
state++;
} while (symbol != foundStateSymbol);
if (state[0].Frequency >= state[-1].Frequency)
{
Swap(state[0], state[-1]);
state--;
}
}
cf = (uint)((state.Frequency < MaximumFrequency - 9) ? 2 : 0);
state.Frequency += (byte)cf;
context.SummaryFrequency += (byte)cf;
}
else
{
state = context.FirstState;
state.Frequency += (byte)((state.Frequency < 32) ? 1 : 0);
}
}
if (orderFall == 0 && foundStateSuccessor != PpmContext.Zero)
{
foundState.Successor = CreateSuccessors(true, state, minimumContext);
if (foundState.Successor == PpmContext.Zero)
goto RestartModel;
maximumContext = foundState.Successor;
return;
}
Allocator.Text[0] = foundStateSymbol;
Allocator.Text++;
Successor = Allocator.Text;
if (Allocator.Text >= Allocator.BaseUnit)
goto RestartModel;
if (foundStateSuccessor != PpmContext.Zero)
{
if (foundStateSuccessor < Allocator.BaseUnit)
foundStateSuccessor = CreateSuccessors(false, state, minimumContext);
}
else
{
foundStateSuccessor = ReduceOrder(state, minimumContext);
}
if (foundStateSuccessor == PpmContext.Zero)
goto RestartModel;
if (--orderFall == 0)
{
Successor = foundStateSuccessor;
Allocator.Text -= (maximumContext != minimumContext) ? 1 : 0;
}
else if (method > ModelRestorationMethod.Freeze)
{
Successor = foundStateSuccessor;
Allocator.Text = Allocator.Heap;
orderFall = 0;
}
numberStatistics = minimumContext.NumberStatistics;
s0 = minimumContext.SummaryFrequency - numberStatistics - foundStateFrequency;
flag = (byte)((foundStateSymbol >= 0x40) ? 0x08 : 0x00);
for (; currentContext != minimumContext; currentContext = currentContext.Suffix)
{
ns1 = currentContext.NumberStatistics;
if (ns1 != 0)
{
if ((ns1 & 1) != 0)
{
state = Allocator.ExpandUnits(currentContext.Statistics, (ns1 + 1) >> 1);
if (state == PpmState.Zero)
goto RestartModel;
currentContext.Statistics = state;
}
currentContext.SummaryFrequency += (ushort)((3 * ns1 + 1 < numberStatistics) ? 1 : 0);
}
else
{
state = Allocator.AllocateUnits(1);
if (state == PpmState.Zero)
goto RestartModel;
Copy(state, currentContext.FirstState);
currentContext.Statistics = state;
if (state.Frequency < MaximumFrequency / 4 - 1)
state.Frequency += state.Frequency;
else
state.Frequency = (byte)(MaximumFrequency - 4);
currentContext.SummaryFrequency = (ushort)(state.Frequency + initialEscape + ((numberStatistics > 2) ? 1 : 0));
}
cf = (uint)(2 * foundStateFrequency * (currentContext.SummaryFrequency + 6));
sf = s0 + currentContext.SummaryFrequency;
if (cf < 6 * sf)
{
cf = (uint)(1 + ((cf > sf) ? 1 : 0) + ((cf >= 4 * sf) ? 1 : 0));
currentContext.SummaryFrequency += 4;
}
else
{
cf = (uint)(4 + ((cf > 9 * sf) ? 1 : 0) + ((cf > 12 * sf) ? 1 : 0) + ((cf > 15 * sf) ? 1 : 0));
currentContext.SummaryFrequency += (ushort)cf;
}
state = currentContext.Statistics + (++currentContext.NumberStatistics);
state.Successor = Successor;
state.Symbol = foundStateSymbol;
state.Frequency = (byte)cf;
currentContext.Flags |= flag;
}
maximumContext = foundStateSuccessor;
return;
RestartModel:
RestoreModel(currentContext, minimumContext, foundStateSuccessor);
}
private PpmContext CreateSuccessors(bool skip, PpmState state, PpmContext context)
{
PpmContext upBranch = foundState.Successor;
PpmState[] states = new PpmState[MaximumOrder];
uint stateIndex = 0;
byte symbol = foundState.Symbol;
if (!skip)
{
states[stateIndex++] = foundState;
if (context.Suffix == PpmContext.Zero)
goto NoLoop;
}
bool gotoLoopEntry = false;
if (state != PpmState.Zero)
{
context = context.Suffix;
gotoLoopEntry = true;
}
do
{
if (gotoLoopEntry)
{
gotoLoopEntry = false;
goto LoopEntry;
}
context = context.Suffix;
if (context.NumberStatistics != 0)
{
byte temporary;
state = context.Statistics;
if (state.Symbol != symbol)
{
do
{
temporary = state[1].Symbol;
state++;
} while (temporary != symbol);
}
temporary = (byte)((state.Frequency < MaximumFrequency - 9) ? 1 : 0);
state.Frequency += temporary;
context.SummaryFrequency += temporary;
}
else
{
state = context.FirstState;
state.Frequency += (byte)(((context.Suffix.NumberStatistics == 0) ? 1 : 0) & ((state.Frequency < 24) ? 1 : 0));
}
LoopEntry:
if (state.Successor != upBranch)
{
context = state.Successor;
break;
}
states[stateIndex++] = state;
} while (context.Suffix != PpmContext.Zero);
NoLoop:
if (stateIndex == 0)
return context;
byte localNumberStatistics = 0;
byte localFlags = (byte)((symbol >= 0x40) ? 0x10 : 0x00);
symbol = upBranch.NumberStatistics;
byte localSymbol = symbol;
byte localFrequency;
PpmContext localSuccessor = ((Pointer)upBranch) + 1;
localFlags |= (byte)((symbol >= 0x40) ? 0x08 : 0x00);
if (context.NumberStatistics != 0)
{
state = context.Statistics;
if (state.Symbol != symbol)
{
byte temporary;
do
{
temporary = state[1].Symbol;
state++;
} while (temporary != symbol);
}
uint cf = (uint)(state.Frequency - 1);
uint s0 = (uint)(context.SummaryFrequency - context.NumberStatistics - cf);
localFrequency = (byte)(1 + ((2 * cf <= s0) ? (uint)((5 * cf > s0) ? 1 : 0) : ((cf + 2 * s0 - 3) / s0)));
}
else
{
localFrequency = context.FirstStateFrequency;
}
do
{
PpmContext currentContext = Allocator.AllocateContext();
if (currentContext == PpmContext.Zero)
return PpmContext.Zero;
currentContext.NumberStatistics = localNumberStatistics;
currentContext.Flags = localFlags;
currentContext.FirstStateSymbol = localSymbol;
currentContext.FirstStateFrequency = localFrequency;
currentContext.FirstStateSuccessor = localSuccessor;
currentContext.Suffix = context;
context = currentContext;
states[--stateIndex].Successor = context;
} while (stateIndex != 0);
return context;
}
private PpmContext ReduceOrder(PpmState state, PpmContext context)
{
PpmState currentState;
PpmState[] states = new PpmState[MaximumOrder];
uint stateIndex = 0;
PpmContext currentContext = context;
PpmContext UpBranch = Allocator.Text;
byte temporary;
byte symbol = foundState.Symbol;
states[stateIndex++] = foundState;
foundState.Successor = UpBranch;
orderFall++;
bool gotoLoopEntry = false;
if (state != PpmState.Zero)
{
context = context.Suffix;
gotoLoopEntry = true;
}
while (true)
{
if (gotoLoopEntry)
{
gotoLoopEntry = false;
goto LoopEntry;
}
if (context.Suffix == PpmContext.Zero)
{
if (method > ModelRestorationMethod.Freeze)
{
do
{
states[--stateIndex].Successor = context;
} while (stateIndex != 0);
Allocator.Text = Allocator.Heap + 1;
orderFall = 1;
}
return context;
}
context = context.Suffix;
if (context.NumberStatistics != 0)
{
state = context.Statistics;
if (state.Symbol != symbol)
{
do
{
temporary = state[1].Symbol;
state++;
} while (temporary != symbol);
}
temporary = (byte)((state.Frequency < MaximumFrequency - 9) ? 2 : 0);
state.Frequency += temporary;
context.SummaryFrequency += temporary;
}
else
{
state = context.FirstState;
state.Frequency += (byte)((state.Frequency < 32) ? 1 : 0);
}
LoopEntry:
if (state.Successor != PpmContext.Zero)
break;
states[stateIndex++] = state;
state.Successor = UpBranch;
orderFall++;
}
if (method > ModelRestorationMethod.Freeze)
{
context = state.Successor;
do
{
states[--stateIndex].Successor = context;
} while (stateIndex != 0);
Allocator.Text = Allocator.Heap + 1;
orderFall = 1;
return context;
}
else if (state.Successor <= UpBranch)
{
currentState = foundState;
foundState = state;
state.Successor = CreateSuccessors(false, PpmState.Zero, context);
foundState = currentState;
}
if (orderFall == 1 && currentContext == maximumContext)
{
foundState.Successor = state.Successor;
Allocator.Text--;
}
return state.Successor;
}
private void RestoreModel(PpmContext context, PpmContext minimumContext, PpmContext foundStateSuccessor)
{
PpmContext currentContext;
Allocator.Text = Allocator.Heap;
for (currentContext = maximumContext; currentContext != context; currentContext = currentContext.Suffix)
{
if (--currentContext.NumberStatistics == 0)
{
currentContext.Flags = (byte)((currentContext.Flags & 0x10) + ((currentContext.Statistics.Symbol >= 0x40) ? 0x08 : 0x00));
PpmState state = currentContext.Statistics;
Copy(currentContext.FirstState, state);
Allocator.SpecialFreeUnits(state);
currentContext.FirstStateFrequency = (byte)((currentContext.FirstStateFrequency + 11) >> 3);
}
else
{
Refresh((uint)((currentContext.NumberStatistics + 3) >> 1), false, currentContext);
}
}
for (; currentContext != minimumContext; currentContext = currentContext.Suffix)
{
if (currentContext.NumberStatistics == 0)
currentContext.FirstStateFrequency -= (byte)(currentContext.FirstStateFrequency >> 1);
else if ((currentContext.SummaryFrequency += 4) > 128 + 4 * currentContext.NumberStatistics)
Refresh((uint)((currentContext.NumberStatistics + 2) >> 1), true, currentContext);
}
if (method > ModelRestorationMethod.Freeze)
{
maximumContext = foundStateSuccessor;
Allocator.GlueCount += (uint)(((Allocator.MemoryNodes[1].Stamp & 1) == 0) ? 1 : 0);
}
else if (method == ModelRestorationMethod.Freeze)
{
while (maximumContext.Suffix != PpmContext.Zero)
maximumContext = maximumContext.Suffix;
RemoveBinaryContexts(0, maximumContext);
method = (ModelRestorationMethod)(method + 1);
Allocator.GlueCount = 0;
orderFall = modelOrder;
}
else if (method == ModelRestorationMethod.Restart || Allocator.GetMemoryUsed() < (Allocator.AllocatorSize >> 1))
{
StartModel(modelOrder, method);
escapeCount = 0;
}
else
{
while (maximumContext.Suffix != PpmContext.Zero)
maximumContext = maximumContext.Suffix;
do
{
CutOff(0, maximumContext);
Allocator.ExpandText();
} while (Allocator.GetMemoryUsed() > 3 * (Allocator.AllocatorSize >> 2));
Allocator.GlueCount = 0;
orderFall = modelOrder;
}
}
private static void Swap(PpmState state1, PpmState state2)
{
byte swapSymbol = state1.Symbol;
byte swapFrequency = state1.Frequency;
PpmContext swapSuccessor = state1.Successor;
state1.Symbol = state2.Symbol;
state1.Frequency = state2.Frequency;
state1.Successor = state2.Successor;
state2.Symbol = swapSymbol;
state2.Frequency = swapFrequency;
state2.Successor = swapSuccessor;
}
private static void Copy(PpmState state1, PpmState state2)
{
state1.Symbol = state2.Symbol;
state1.Frequency = state2.Frequency;
state1.Successor = state2.Successor;
}
private static int Mean(int sum, int shift, int round)
{
return (sum + (1 << (shift - round))) >> shift;
}
private void ClearMask()
{
escapeCount = 1;
Array.Clear(characterMask, 0, characterMask.Length);
}
#endregion
}
}

View File

@@ -1,29 +0,0 @@
#region Using
#endregion
namespace Compress.SevenZip.Compress.PPmd.I1
{
/// <summary>
/// The method used to adjust the model when the memory limit is reached.
/// </summary>
internal enum ModelRestorationMethod
{
/// <summary>
/// Restart the model from scratch (this is the default).
/// </summary>
Restart = 0,
/// <summary>
/// Cut off the model (nearly twice as slow).
/// </summary>
CutOff = 1,
/// <summary>
/// Freeze the context tree (in some cases may result in poor compression).
/// </summary>
Freeze = 2
}
}

View File

@@ -1,319 +0,0 @@
#region Using
using System;
#endregion
namespace Compress.SevenZip.Compress.PPmd.I1
{
/// <summary>
/// A structure containing a single address representing a position in the <see cref="Memory"/> array. This
/// is intended to mimic the behaviour of a pointer in C/C++.
/// </summary>
/// <remarks>
/// <para>
/// This must be a structure rather than a class because several places in the associated code assume that
/// <see cref="Pointer"/> is a value type (meaning that assignment creates a completely new copy of the
/// instance rather than just copying a reference to the same instance).
/// </para>
/// <para>
/// Note that <see cref="Address"/> is a field rather than a property for performance reasons.
/// </para>
/// </remarks>
internal struct Pointer
{
public uint Address;
public byte[] Memory;
public static readonly Pointer Zero = new Pointer(0, null);
public const int Size = 1;
/// <summary>
/// Initializes a new instance of the <see cref="Pointer"/> structure.
/// </summary>
public Pointer(uint address, byte[] memory)
{
Address = address;
Memory = memory;
}
/// <summary>
/// Gets or sets the byte at the given <paramref name="offset"/>.
/// </summary>
/// <param name="offset"></param>
/// <returns></returns>
public byte this[int offset]
{
get
{
#if DEBUG
if (Address == 0)
throw new InvalidOperationException("The pointer being indexed is a null pointer.");
#endif
return Memory[Address + offset];
}
set
{
#if DEBUG
if (Address == 0)
throw new InvalidOperationException("The pointer being indexed is a null pointer.");
#endif
Memory[Address + offset] = value;
}
}
/// <summary>
/// Allow a <see cref="MemoryNode"/> to be implicitly converted to a <see cref="Pointer"/>.
/// </summary>
/// <param name="memoryNode"></param>
/// <returns></returns>
public static implicit operator Pointer(MemoryNode memoryNode)
{
return new Pointer(memoryNode.Address, memoryNode.Memory);
}
/// <summary>
/// Allow a <see cref="Model.PpmContext"/> to be implicitly converted to a <see cref="Pointer"/>.
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public static implicit operator Pointer(Model.PpmContext context)
{
return new Pointer(context.Address, context.Memory);
}
/// <summary>
/// Allow a <see cref="PpmState"/> to be implicitly converted to a <see cref="Pointer"/>.
/// </summary>
/// <param name="state"></param>
/// <returns></returns>
public static implicit operator Pointer(PpmState state)
{
return new Pointer(state.Address, state.Memory);
}
/// <summary>
/// Increase the address of a pointer by the given number of bytes.
/// </summary>
/// <param name="pointer"></param>
/// <param name="offset"></param>
/// <returns></returns>
public static Pointer operator +(Pointer pointer, int offset)
{
#if DEBUG
if (pointer.Address == 0)
throw new InvalidOperationException("The pointer is a null pointer.");
#endif
pointer.Address = (uint)(pointer.Address + offset);
return pointer;
}
/// <summary>
/// Increase the address of a pointer by the given number of bytes.
/// </summary>
/// <param name="pointer"></param>
/// <param name="offset"></param>
/// <returns></returns>
public static Pointer operator +(Pointer pointer, uint offset)
{
#if DEBUG
if (pointer.Address == 0)
throw new InvalidOperationException("The pointer is a null pointer.");
#endif
pointer.Address += offset;
return pointer;
}
/// <summary>
/// Increment the address of a pointer.
/// </summary>
/// <param name="pointer"></param>
/// <returns></returns>
public static Pointer operator ++(Pointer pointer)
{
#if DEBUG
if (pointer.Address == 0)
throw new InvalidOperationException("The pointer being incremented is a null pointer.");
#endif
pointer.Address++;
return pointer;
}
/// <summary>
/// Decrease the address of a pointer by the given number of bytes.
/// </summary>
/// <param name="pointer"></param>
/// <param name="offset"></param>
/// <returns></returns>
public static Pointer operator -(Pointer pointer, int offset)
{
#if DEBUG
if (pointer.Address == 0)
throw new InvalidOperationException("The pointer is a null pointer.");
#endif
pointer.Address = (uint)(pointer.Address - offset);
return pointer;
}
/// <summary>
/// Decrease the address of a pointer by the given number of bytes.
/// </summary>
/// <param name="pointer"></param>
/// <param name="offset"></param>
/// <returns></returns>
public static Pointer operator -(Pointer pointer, uint offset)
{
#if DEBUG
if (pointer.Address == 0)
throw new InvalidOperationException("The pointer is a null pointer.");
#endif
pointer.Address -= offset;
return pointer;
}
/// <summary>
/// Decrement the address of a pointer.
/// </summary>
/// <param name="pointer"></param>
/// <returns></returns>
public static Pointer operator --(Pointer pointer)
{
#if DEBUG
if (pointer.Address == 0)
throw new InvalidOperationException("The pointer being decremented is a null pointer.");
#endif
pointer.Address--;
return pointer;
}
/// <summary>
/// Subtract two pointers.
/// </summary>
/// <param name="pointer1"></param>
/// <param name="pointer2"></param>
/// <returns>The number of bytes between the two pointers.</returns>
public static uint operator -(Pointer pointer1, Pointer pointer2)
{
#if DEBUG
if (pointer1.Address == 0)
throw new InvalidOperationException("The pointer to the left of the subtraction operator is a null pointer.");
if (pointer2.Address == 0)
throw new InvalidOperationException("The pointer to the right of the subtraction operator is a null pointer.");
#endif
return pointer1.Address - pointer2.Address;
}
/// <summary>
/// Compare pointers.
/// </summary>
/// <param name="pointer1"></param>
/// <param name="pointer2"></param>
/// <returns></returns>
public static bool operator <(Pointer pointer1, Pointer pointer2)
{
#if DEBUG
if (pointer1.Address == 0)
throw new InvalidOperationException("The pointer to the left of the less than operator is a null pointer.");
if (pointer2.Address == 0)
throw new InvalidOperationException("The pointer to the right of the less than operator is a null pointer.");
#endif
return pointer1.Address < pointer2.Address;
}
/// <summary>
/// Compare two pointers.
/// </summary>
/// <param name="pointer1"></param>
/// <param name="pointer2"></param>
/// <returns></returns>
public static bool operator <=(Pointer pointer1, Pointer pointer2)
{
#if DEBUG
if (pointer1.Address == 0)
throw new InvalidOperationException("The pointer to the left of the less than or equal to operator is a null pointer.");
if (pointer2.Address == 0)
throw new InvalidOperationException("The pointer to the right of the less than or equal to operator is a null pointer.");
#endif
return pointer1.Address <= pointer2.Address;
}
/// <summary>
/// Compare two pointers.
/// </summary>
/// <param name="pointer1"></param>
/// <param name="pointer2"></param>
/// <returns></returns>
public static bool operator >(Pointer pointer1, Pointer pointer2)
{
#if DEBUG
if (pointer1.Address == 0)
throw new InvalidOperationException("The pointer to the left of the greater than operator is a null pointer.");
if (pointer2.Address == 0)
throw new InvalidOperationException("The pointer to the right of the greater than operator is a null pointer.");
#endif
return pointer1.Address > pointer2.Address;
}
/// <summary>
/// Compare two pointers.
/// </summary>
/// <param name="pointer1"></param>
/// <param name="pointer2"></param>
/// <returns></returns>
public static bool operator >=(Pointer pointer1, Pointer pointer2)
{
#if DEBUG
if (pointer1.Address == 0)
throw new InvalidOperationException("The pointer to the left of the greater than or equal to operator is a null pointer.");
if (pointer2.Address == 0)
throw new InvalidOperationException("The pointer to the right of the greater than or equal to operator is a null pointer.");
#endif
return pointer1.Address >= pointer2.Address;
}
/// <summary>
/// Compare two pointers.
/// </summary>
/// <param name="pointer1"></param>
/// <param name="pointer2"></param>
/// <returns></returns>
public static bool operator ==(Pointer pointer1, Pointer pointer2)
{
return pointer1.Address == pointer2.Address;
}
/// <summary>
/// Compare two pointers.
/// </summary>
/// <param name="pointer1"></param>
/// <param name="pointer2"></param>
/// <returns></returns>
public static bool operator !=(Pointer pointer1, Pointer pointer2)
{
return pointer1.Address != pointer2.Address;
}
/// <summary>
/// Indicates whether this instance and a specified object are equal.
/// </summary>
/// <returns>true if obj and this instance are the same type and represent the same value; otherwise, false.</returns>
/// <param name="obj">Another object to compare to.</param>
public override bool Equals(object obj)
{
if (obj is Pointer)
{
Pointer pointer = (Pointer)obj;
return pointer.Address == Address;
}
return base.Equals(obj);
}
/// <summary>
/// Returns the hash code for this instance.
/// </summary>
/// <returns>A 32-bit signed integer that is the hash code for this instance.</returns>
public override int GetHashCode()
{
return Address.GetHashCode();
}
}
}

View File

@@ -1,787 +0,0 @@
#region Using
#endregion
namespace Compress.SevenZip.Compress.PPmd.I1
{
/// <summary>
/// The PPM context structure. This is tightly coupled with <see cref="Model"/>.
/// </summary>
/// <remarks>
/// <para>
/// This must be a structure rather than a class because several places in the associated code assume that
/// <see cref="PpmContext"/> is a value type (meaning that assignment creates a completely new copy of
/// the instance rather than just copying a reference to the same instance).
/// </para>
/// </remarks>
internal partial class Model
{
/// <summary>
/// The structure which represents the current PPM context. This is 12 bytes in size.
/// </summary>
internal struct PpmContext
{
public uint Address;
public byte[] Memory;
public static readonly PpmContext Zero = new PpmContext(0, null);
public const int Size = 12;
/// <summary>
/// Initializes a new instance of the <see cref="PpmContext"/> structure.
/// </summary>
public PpmContext(uint address, byte[] memory)
{
Address = address;
Memory = memory;
}
/// <summary>
/// Gets or sets the number statistics.
/// </summary>
public byte NumberStatistics
{
get { return Memory[Address]; }
set { Memory[Address] = value; }
}
/// <summary>
/// Gets or sets the flags.
/// </summary>
public byte Flags
{
get { return Memory[Address + 1]; }
set { Memory[Address + 1] = value; }
}
/// <summary>
/// Gets or sets the summary frequency.
/// </summary>
public ushort SummaryFrequency
{
get { return (ushort)(((ushort)Memory[Address + 2]) | ((ushort)Memory[Address + 3]) << 8); }
set
{
Memory[Address + 2] = (byte)value;
Memory[Address + 3] = (byte)(value >> 8);
}
}
/// <summary>
/// Gets or sets the statistics.
/// </summary>
public PpmState Statistics
{
get { return new PpmState(((uint)Memory[Address + 4]) | ((uint)Memory[Address + 5]) << 8 | ((uint)Memory[Address + 6]) << 16 | ((uint)Memory[Address + 7]) << 24, Memory); }
set
{
Memory[Address + 4] = (byte)value.Address;
Memory[Address + 5] = (byte)(value.Address >> 8);
Memory[Address + 6] = (byte)(value.Address >> 16);
Memory[Address + 7] = (byte)(value.Address >> 24);
}
}
/// <summary>
/// Gets or sets the suffix.
/// </summary>
public PpmContext Suffix
{
get { return new PpmContext(((uint)Memory[Address + 8]) | ((uint)Memory[Address + 9]) << 8 | ((uint)Memory[Address + 10]) << 16 | ((uint)Memory[Address + 11]) << 24, Memory); }
set
{
Memory[Address + 8] = (byte)value.Address;
Memory[Address + 9] = (byte)(value.Address >> 8);
Memory[Address + 10] = (byte)(value.Address >> 16);
Memory[Address + 11] = (byte)(value.Address >> 24);
}
}
/// <summary>
/// The first PPM state associated with the PPM context.
/// </summary>
/// <remarks>
/// <para>
/// The first PPM state overlaps this PPM context instance (the context.SummaryFrequency and context.Statistics members
/// of PpmContext use 6 bytes and so can therefore fit into the space used by the Symbol, Frequency and
/// Successor members of PpmState, since they also add up to 6 bytes).
/// </para>
/// <para>
/// PpmContext (context.SummaryFrequency and context.Statistics use 6 bytes)
/// 1 context.NumberStatistics
/// 1 context.Flags
/// 2 context.SummaryFrequency
/// 4 context.Statistics (pointer to PpmState)
/// 4 context.Suffix (pointer to PpmContext)
/// </para>
/// <para>
/// PpmState (total of 6 bytes)
/// 1 Symbol
/// 1 Frequency
/// 4 Successor (pointer to PpmContext)
/// </para>
/// </remarks>
/// <returns></returns>
public PpmState FirstState
{
get { return new PpmState(Address + 2, Memory); }
}
/// <summary>
/// Gets or sets the symbol of the first PPM state. This is provided for convenience. The same
/// information can be obtained using the Symbol property on the PPM state provided by the
/// <see cref="FirstState"/> property.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "The property getter is provided for completeness.")]
public byte FirstStateSymbol
{
get { return Memory[Address + 2]; }
set { Memory[Address + 2] = value; }
}
/// <summary>
/// Gets or sets the frequency of the first PPM state. This is provided for convenience. The same
/// information can be obtained using the Frequency property on the PPM state provided by the
///context.FirstState property.
/// </summary>
public byte FirstStateFrequency
{
get { return Memory[Address + 3]; }
set { Memory[Address + 3] = value; }
}
/// <summary>
/// Gets or sets the successor of the first PPM state. This is provided for convenience. The same
/// information can be obtained using the Successor property on the PPM state provided by the
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "The property getter is provided for completeness.")]
public PpmContext FirstStateSuccessor
{
get { return new PpmContext(((uint)Memory[Address + 4]) | ((uint)Memory[Address + 5]) << 8 | ((uint)Memory[Address + 6]) << 16 | ((uint)Memory[Address + 7]) << 24, Memory); }
set
{
Memory[Address + 4] = (byte)value.Address;
Memory[Address + 5] = (byte)(value.Address >> 8);
Memory[Address + 6] = (byte)(value.Address >> 16);
Memory[Address + 7] = (byte)(value.Address >> 24);
}
}
/// <summary>
/// Allow a pointer to be implicitly converted to a PPM context.
/// </summary>
/// <param name="pointer"></param>
/// <returns></returns>
public static implicit operator PpmContext(Pointer pointer)
{
return new PpmContext(pointer.Address, pointer.Memory);
}
/// <summary>
/// Allow pointer-like addition on a PPM context.
/// </summary>
/// <param name="context"></param>
/// <param name="offset"></param>
/// <returns></returns>
public static PpmContext operator +(PpmContext context, int offset)
{
context.Address = (uint)(context.Address + offset * Size);
return context;
}
/// <summary>
/// Allow pointer-like subtraction on a PPM context.
/// </summary>
/// <param name="context"></param>
/// <param name="offset"></param>
/// <returns></returns>
public static PpmContext operator -(PpmContext context, int offset)
{
context.Address = (uint)(context.Address - offset * Size);
return context;
}
/// <summary>
/// Compare two PPM contexts.
/// </summary>
/// <param name="context1"></param>
/// <param name="context2"></param>
/// <returns></returns>
public static bool operator <=(PpmContext context1, PpmContext context2)
{
return context1.Address <= context2.Address;
}
/// <summary>
/// Compare two PPM contexts.
/// </summary>
/// <param name="context1"></param>
/// <param name="context2"></param>
/// <returns></returns>
public static bool operator >=(PpmContext context1, PpmContext context2)
{
return context1.Address >= context2.Address;
}
/// <summary>
/// Compare two PPM contexts.
/// </summary>
/// <param name="context1"></param>
/// <param name="context2"></param>
/// <returns></returns>
public static bool operator ==(PpmContext context1, PpmContext context2)
{
return context1.Address == context2.Address;
}
/// <summary>
/// Compare two PPM contexts.
/// </summary>
/// <param name="context1"></param>
/// <param name="context2"></param>
/// <returns></returns>
public static bool operator !=(PpmContext context1, PpmContext context2)
{
return context1.Address != context2.Address;
}
/// <summary>
/// Indicates whether this instance and a specified object are equal.
/// </summary>
/// <returns>true if obj and this instance are the same type and represent the same value; otherwise, false.</returns>
/// <param name="obj">Another object to compare to.</param>
public override bool Equals(object obj)
{
if (obj is PpmContext)
{
PpmContext context = (PpmContext)obj;
return context.Address == Address;
}
return base.Equals(obj);
}
/// <summary>
/// Returns the hash code for this instance.
/// </summary>
/// <returns>A 32-bit signed integer that is the hash code for this instance.</returns>
public override int GetHashCode()
{
return Address.GetHashCode();
}
}
private void EncodeBinarySymbol(int symbol, PpmContext context)
{
PpmState state = context.FirstState;
int index1 = probabilities[state.Frequency - 1];
int index2 = numberStatisticsToBinarySummaryIndex[context.Suffix.NumberStatistics] + previousSuccess + context.Flags + ((runLength >> 26) & 0x20);
if (state.Symbol == symbol)
{
foundState = state;
state.Frequency += (byte)((state.Frequency < 196) ? 1 : 0);
Coder.LowCount = 0;
Coder.HighCount = binarySummary[index1, index2];
binarySummary[index1, index2] += (ushort)(Interval - Mean(binarySummary[index1, index2], PeriodBitCount, 2));
previousSuccess = 1;
runLength++;
}
else
{
Coder.LowCount = binarySummary[index1, index2];
binarySummary[index1, index2] -= (ushort)Mean(binarySummary[index1, index2], PeriodBitCount, 2);
Coder.HighCount = BinaryScale;
initialEscape = ExponentialEscapes[binarySummary[index1, index2] >> 10];
characterMask[state.Symbol] = escapeCount;
previousSuccess = 0;
numberMasked = 0;
foundState = PpmState.Zero;
}
}
private void EncodeSymbol1(int symbol, PpmContext context)
{
uint lowCount;
uint index = context.Statistics.Symbol;
PpmState state = context.Statistics;
Coder.Scale = context.SummaryFrequency;
if (index == symbol)
{
Coder.HighCount = state.Frequency;
previousSuccess = (byte)((2 * Coder.HighCount >= Coder.Scale) ? 1 : 0);
foundState = state;
foundState.Frequency += 4;
context.SummaryFrequency += 4;
runLength += previousSuccess;
if (state.Frequency > MaximumFrequency)
Rescale(context);
Coder.LowCount = 0;
return;
}
lowCount = state.Frequency;
index = context.NumberStatistics;
previousSuccess = 0;
while ((++state).Symbol != symbol)
{
lowCount += state.Frequency;
if (--index == 0)
{
Coder.LowCount = lowCount;
characterMask[state.Symbol] = escapeCount;
numberMasked = context.NumberStatistics;
index = context.NumberStatistics;
foundState = PpmState.Zero;
do
{
characterMask[(--state).Symbol] = escapeCount;
} while (--index != 0);
Coder.HighCount = Coder.Scale;
return;
}
}
Coder.HighCount = (Coder.LowCount = lowCount) + state.Frequency;
Update1(state, context);
}
private void EncodeSymbol2(int symbol, PpmContext context)
{
See2Context see2Context = MakeEscapeFrequency(context);
uint currentSymbol;
uint lowCount = 0;
uint index = (uint)(context.NumberStatistics - numberMasked);
PpmState state = context.Statistics - 1;
do
{
do
{
currentSymbol = state[1].Symbol;
state++;
} while (characterMask[currentSymbol] == escapeCount);
characterMask[currentSymbol] = escapeCount;
if (currentSymbol == symbol)
goto SymbolFound;
lowCount += state.Frequency;
} while (--index != 0);
Coder.LowCount = lowCount;
Coder.Scale += Coder.LowCount;
Coder.HighCount = Coder.Scale;
see2Context.Summary += (ushort)Coder.Scale;
numberMasked = context.NumberStatistics;
return;
SymbolFound:
Coder.LowCount = lowCount;
lowCount += state.Frequency;
Coder.HighCount = lowCount;
for (PpmState p1 = state; --index != 0;)
{
do
{
currentSymbol = p1[1].Symbol;
p1++;
} while (characterMask[currentSymbol] == escapeCount);
lowCount += p1.Frequency;
}
Coder.Scale += lowCount;
see2Context.Update();
Update2(state, context);
}
private void DecodeBinarySymbol(PpmContext context)
{
PpmState state = context.FirstState;
int index1 = probabilities[state.Frequency - 1];
int index2 = numberStatisticsToBinarySummaryIndex[context.Suffix.NumberStatistics] + previousSuccess + context.Flags + ((runLength >> 26) & 0x20);
if (Coder.RangeGetCurrentShiftCount(TotalBitCount) < binarySummary[index1, index2])
{
foundState = state;
state.Frequency += (byte)((state.Frequency < 196) ? 1 : 0);
Coder.LowCount = 0;
Coder.HighCount = binarySummary[index1, index2];
binarySummary[index1, index2] += (ushort)(Interval - Mean(binarySummary[index1, index2], PeriodBitCount, 2));
previousSuccess = 1;
runLength++;
}
else
{
Coder.LowCount = binarySummary[index1, index2];
binarySummary[index1, index2] -= (ushort)Mean(binarySummary[index1, index2], PeriodBitCount, 2);
Coder.HighCount = BinaryScale;
initialEscape = ExponentialEscapes[binarySummary[index1, index2] >> 10];
characterMask[state.Symbol] = escapeCount;
previousSuccess = 0;
numberMasked = 0;
foundState = PpmState.Zero;
}
}
private void DecodeSymbol1(PpmContext context)
{
uint index;
uint count;
uint highCount = context.Statistics.Frequency;
PpmState state = context.Statistics;
Coder.Scale = context.SummaryFrequency;
count = Coder.RangeGetCurrentCount();
if (count < highCount)
{
Coder.HighCount = highCount;
previousSuccess = (byte)((2 * Coder.HighCount >= Coder.Scale) ? 1 : 0);
foundState = state;
highCount += 4;
foundState.Frequency = (byte)highCount;
context.SummaryFrequency += 4;
runLength += previousSuccess;
if (highCount > MaximumFrequency)
Rescale(context);
Coder.LowCount = 0;
return;
}
index = context.NumberStatistics;
previousSuccess = 0;
while ((highCount += (++state).Frequency) <= count)
{
if (--index == 0)
{
Coder.LowCount = highCount;
characterMask[state.Symbol] = escapeCount;
numberMasked = context.NumberStatistics;
index = context.NumberStatistics;
foundState = PpmState.Zero;
do
{
characterMask[(--state).Symbol] = escapeCount;
} while (--index != 0);
Coder.HighCount = Coder.Scale;
return;
}
}
Coder.HighCount = highCount;
Coder.LowCount = Coder.HighCount - state.Frequency;
Update1(state, context);
}
private void DecodeSymbol2(PpmContext context)
{
See2Context see2Context = MakeEscapeFrequency(context);
uint currentSymbol;
uint count;
uint highCount = 0;
uint index = (uint)(context.NumberStatistics - numberMasked);
uint stateIndex = 0;
PpmState state = context.Statistics - 1;
do
{
do
{
currentSymbol = state[1].Symbol;
state++;
} while (characterMask[currentSymbol] == escapeCount);
highCount += state.Frequency;
decodeStates[stateIndex++] = state; // note that decodeStates is a static array that is re-used on each call to this method (for performance reasons)
} while (--index != 0);
Coder.Scale += highCount;
count = Coder.RangeGetCurrentCount();
stateIndex = 0;
state = decodeStates[stateIndex];
if (count < highCount)
{
highCount = 0;
while ((highCount += state.Frequency) <= count)
state = decodeStates[++stateIndex];
Coder.HighCount = highCount;
Coder.LowCount = Coder.HighCount - state.Frequency;
see2Context.Update();
Update2(state, context);
}
else
{
Coder.LowCount = highCount;
Coder.HighCount = Coder.Scale;
index = (uint)(context.NumberStatistics - numberMasked);
numberMasked = context.NumberStatistics;
do
{
characterMask[decodeStates[stateIndex].Symbol] = escapeCount;
stateIndex++;
} while (--index != 0);
see2Context.Summary += (ushort)Coder.Scale;
}
}
private void Update1(PpmState state, PpmContext context)
{
foundState = state;
foundState.Frequency += 4;
context.SummaryFrequency += 4;
if (state[0].Frequency > state[-1].Frequency)
{
Swap(state[0], state[-1]);
foundState = --state;
if (state.Frequency > MaximumFrequency)
Rescale(context);
}
}
private void Update2(PpmState state, PpmContext context)
{
foundState = state;
foundState.Frequency += 4;
context.SummaryFrequency += 4;
if (state.Frequency > MaximumFrequency)
Rescale(context);
escapeCount++;
runLength = initialRunLength;
}
private See2Context MakeEscapeFrequency(PpmContext context)
{
uint numberStatistics = (uint)2 * context.NumberStatistics;
See2Context see2Context;
if (context.NumberStatistics != 0xff)
{
// Note that context.Flags is always in the range 0 .. 28 (this ensures that the index used for the second
// dimension of the see2Contexts array is always in the range 0 .. 31).
numberStatistics = context.Suffix.NumberStatistics;
int index1 = probabilities[context.NumberStatistics + 2] - 3;
int index2 = ((context.SummaryFrequency > 11 * (context.NumberStatistics + 1)) ? 1 : 0) + ((2 * context.NumberStatistics < numberStatistics + numberMasked) ? 2 : 0) + context.Flags;
see2Context = see2Contexts[index1, index2];
Coder.Scale = see2Context.Mean();
}
else
{
see2Context = emptySee2Context;
Coder.Scale = 1;
}
return see2Context;
}
private void Rescale(PpmContext context)
{
uint oldUnitCount;
int adder;
uint escapeFrequency;
uint index = context.NumberStatistics;
byte localSymbol;
byte localFrequency;
PpmContext localSuccessor;
PpmState p1;
PpmState state;
for (state = foundState; state != context.Statistics; state--)
Swap(state[0], state[-1]);
state.Frequency += 4;
context.SummaryFrequency += 4;
escapeFrequency = (uint)(context.SummaryFrequency - state.Frequency);
adder = (orderFall != 0 || method > ModelRestorationMethod.Freeze) ? 1 : 0;
state.Frequency = (byte)((state.Frequency + adder) >> 1);
context.SummaryFrequency = state.Frequency;
do
{
escapeFrequency -= (++state).Frequency;
state.Frequency = (byte)((state.Frequency + adder) >> 1);
context.SummaryFrequency += state.Frequency;
if (state[0].Frequency > state[-1].Frequency)
{
p1 = state;
localSymbol = p1.Symbol;
localFrequency = p1.Frequency;
localSuccessor = p1.Successor;
do
{
Copy(p1[0], p1[-1]);
} while (localFrequency > (--p1)[-1].Frequency);
p1.Symbol = localSymbol;
p1.Frequency = localFrequency;
p1.Successor = localSuccessor;
}
} while (--index != 0);
if (state.Frequency == 0)
{
do
{
index++;
} while ((--state).Frequency == 0);
escapeFrequency += index;
oldUnitCount = (uint)((context.NumberStatistics + 2) >> 1);
context.NumberStatistics -= (byte)index;
if (context.NumberStatistics == 0)
{
localSymbol = context.Statistics.Symbol;
localFrequency = context.Statistics.Frequency;
localSuccessor = context.Statistics.Successor;
localFrequency = (byte)((2 * localFrequency + escapeFrequency - 1) / escapeFrequency);
if (localFrequency > MaximumFrequency / 3)
localFrequency = (byte)(MaximumFrequency / 3);
Allocator.FreeUnits(context.Statistics, oldUnitCount);
context.FirstStateSymbol = localSymbol;
context.FirstStateFrequency = localFrequency;
context.FirstStateSuccessor = localSuccessor;
context.Flags = (byte)((context.Flags & 0x10) + ((localSymbol >= 0x40) ? 0x08 : 0x00));
foundState = context.FirstState;
return;
}
context.Statistics = Allocator.ShrinkUnits(context.Statistics, oldUnitCount, (uint)((context.NumberStatistics + 2) >> 1));
context.Flags &= 0xf7;
index = context.NumberStatistics;
state = context.Statistics;
context.Flags |= (byte)((state.Symbol >= 0x40) ? 0x08 : 0x00);
do
{
context.Flags |= (byte)(((++state).Symbol >= 0x40) ? 0x08 : 0x00);
} while (--index != 0);
}
escapeFrequency -= (escapeFrequency >> 1);
context.SummaryFrequency += (ushort)escapeFrequency;
context.Flags |= 0x04;
foundState = context.Statistics;
}
private void Refresh(uint oldUnitCount, bool scale, PpmContext context)
{
int index = context.NumberStatistics;
int escapeFrequency;
int scaleValue = (scale ? 1 : 0);
context.Statistics = Allocator.ShrinkUnits(context.Statistics, oldUnitCount, (uint)((index + 2) >> 1));
PpmState statistics = context.Statistics;
context.Flags = (byte)((context.Flags & (0x10 + (scale ? 0x04 : 0x00))) + ((statistics.Symbol >= 0x40) ? 0x08 : 0x00));
escapeFrequency = context.SummaryFrequency - statistics.Frequency;
statistics.Frequency = (byte)((statistics.Frequency + scaleValue) >> scaleValue);
context.SummaryFrequency = statistics.Frequency;
do
{
escapeFrequency -= (++statistics).Frequency;
statistics.Frequency = (byte)((statistics.Frequency + scaleValue) >> scaleValue);
context.SummaryFrequency += statistics.Frequency;
context.Flags |= (byte)((statistics.Symbol >= 0x40) ? 0x08 : 0x00);
} while (--index != 0);
escapeFrequency = (escapeFrequency + scaleValue) >> scaleValue;
context.SummaryFrequency += (ushort)escapeFrequency;
}
private PpmContext CutOff(int order, PpmContext context)
{
int index;
PpmState state;
if (context.NumberStatistics == 0)
{
state = context.FirstState;
if ((Pointer)state.Successor >= Allocator.BaseUnit)
{
if (order < modelOrder)
state.Successor = CutOff(order + 1, state.Successor);
else
state.Successor = PpmContext.Zero;
if (state.Successor == PpmContext.Zero && order > OrderBound)
{
Allocator.SpecialFreeUnits(context);
return PpmContext.Zero;
}
return context;
}
else
{
Allocator.SpecialFreeUnits(context);
return PpmContext.Zero;
}
}
uint unitCount = (uint)((context.NumberStatistics + 2) >> 1);
context.Statistics = Allocator.MoveUnitsUp(context.Statistics, unitCount);
index = context.NumberStatistics;
for (state = context.Statistics + index; state >= context.Statistics; state--)
{
if (state.Successor < Allocator.BaseUnit)
{
state.Successor = PpmContext.Zero;
Swap(state, context.Statistics[index--]);
}
else if (order < modelOrder)
state.Successor = CutOff(order + 1, state.Successor);
else
state.Successor = PpmContext.Zero;
}
if (index != context.NumberStatistics && order != 0)
{
context.NumberStatistics = (byte)index;
state = context.Statistics;
if (index < 0)
{
Allocator.FreeUnits(state, unitCount);
Allocator.SpecialFreeUnits(context);
return PpmContext.Zero;
}
else if (index == 0)
{
context.Flags = (byte)((context.Flags & 0x10) + ((state.Symbol >= 0x40) ? 0x08 : 0x00));
Copy(context.FirstState, state);
Allocator.FreeUnits(state, unitCount);
context.FirstStateFrequency = (byte)((context.FirstStateFrequency + 11) >> 3);
}
else
{
Refresh(unitCount, context.SummaryFrequency > 16 * index, context);
}
}
return context;
}
private PpmContext RemoveBinaryContexts(int order, PpmContext context)
{
if (context.NumberStatistics == 0)
{
PpmState state = context.FirstState;
if ((Pointer)state.Successor >= Allocator.BaseUnit && order < modelOrder)
state.Successor = RemoveBinaryContexts(order + 1, state.Successor);
else
state.Successor = PpmContext.Zero;
if ((state.Successor == PpmContext.Zero) && (context.Suffix.NumberStatistics == 0 || context.Suffix.Flags == 0xff))
{
Allocator.FreeUnits(context, 1);
return PpmContext.Zero;
}
else
{
return context;
}
}
for (PpmState state = context.Statistics + context.NumberStatistics; state >= context.Statistics; state--)
{
if ((Pointer)state.Successor >= Allocator.BaseUnit && order < modelOrder)
state.Successor = RemoveBinaryContexts(order + 1, state.Successor);
else
state.Successor = PpmContext.Zero;
}
return context;
}
}
}

View File

@@ -1,206 +0,0 @@
#region Using
#endregion
namespace Compress.SevenZip.Compress.PPmd.I1
{
/// <summary>
/// PPM state.
/// </summary>
/// <remarks>
/// <para>
/// This must be a structure rather than a class because several places in the associated code assume that
/// <see cref="PpmState"/> is a value type (meaning that assignment creates a completely new copy of the
/// instance rather than just copying a reference to the same instance).
/// </para>
/// <para>
/// Note that <see cref="Address"/> is a field rather than a property for performance reasons.
/// </para>
/// </remarks>
internal struct PpmState
{
public uint Address;
public byte[] Memory;
public static readonly PpmState Zero = new PpmState(0, null);
public const int Size = 6;
/// <summary>
/// Initializes a new instance of the <see cref="PpmState"/> structure.
/// </summary>
public PpmState(uint address, byte[] memory)
{
Address = address;
Memory = memory;
}
/// <summary>
/// Gets or sets the symbol.
/// </summary>
public byte Symbol
{
get { return Memory[Address]; }
set { Memory[Address] = value; }
}
/// <summary>
/// Gets or sets the frequency.
/// </summary>
public byte Frequency
{
get { return Memory[Address + 1]; }
set { Memory[Address + 1] = value; }
}
/// <summary>
/// Gets or sets the successor.
/// </summary>
public Model.PpmContext Successor
{
get { return new Model.PpmContext(((uint)Memory[Address + 2]) | ((uint)Memory[Address + 3]) << 8 | ((uint)Memory[Address + 4]) << 16 | ((uint)Memory[Address + 5]) << 24, Memory); }
set
{
Memory[Address + 2] = (byte)value.Address;
Memory[Address + 3] = (byte)(value.Address >> 8);
Memory[Address + 4] = (byte)(value.Address >> 16);
Memory[Address + 5] = (byte)(value.Address >> 24);
}
}
/// <summary>
/// Gets the <see cref="PpmState"/> at the <paramref name="offset"/> relative to this
/// <see cref="PpmState"/>.
/// </summary>
/// <param name="offset"></param>
/// <returns></returns>
public PpmState this[int offset]
{
get { return new PpmState((uint)(Address + offset * Size), Memory); }
}
/// <summary>
/// Allow a pointer to be implicitly converted to a PPM state.
/// </summary>
/// <param name="pointer"></param>
/// <returns></returns>
public static implicit operator PpmState(Pointer pointer)
{
return new PpmState(pointer.Address, pointer.Memory);
}
/// <summary>
/// Allow pointer-like addition on a PPM state.
/// </summary>
/// <param name="state"></param>
/// <param name="offset"></param>
/// <returns></returns>
public static PpmState operator +(PpmState state, int offset)
{
state.Address = (uint)(state.Address + offset * Size);
return state;
}
/// <summary>
/// Allow pointer-like incrementing on a PPM state.
/// </summary>
/// <param name="state"></param>
/// <returns></returns>
public static PpmState operator ++(PpmState state)
{
state.Address += Size;
return state;
}
/// <summary>
/// Allow pointer-like subtraction on a PPM state.
/// </summary>
/// <param name="state"></param>
/// <param name="offset"></param>
/// <returns></returns>
public static PpmState operator -(PpmState state, int offset)
{
state.Address = (uint)(state.Address - offset * Size);
return state;
}
/// <summary>
/// Allow pointer-like decrementing on a PPM state.
/// </summary>
/// <param name="state"></param>
/// <returns></returns>
public static PpmState operator --(PpmState state)
{
state.Address -= Size;
return state;
}
/// <summary>
/// Compare two PPM states.
/// </summary>
/// <param name="state1"></param>
/// <param name="state2"></param>
/// <returns></returns>
public static bool operator <=(PpmState state1, PpmState state2)
{
return state1.Address <= state2.Address;
}
/// <summary>
/// Compare two PPM states.
/// </summary>
/// <param name="state1"></param>
/// <param name="state2"></param>
/// <returns></returns>
public static bool operator >=(PpmState state1, PpmState state2)
{
return state1.Address >= state2.Address;
}
/// <summary>
/// Compare two PPM states.
/// </summary>
/// <param name="state1"></param>
/// <param name="state2"></param>
/// <returns></returns>
public static bool operator ==(PpmState state1, PpmState state2)
{
return state1.Address == state2.Address;
}
/// <summary>
/// Compare two PPM states.
/// </summary>
/// <param name="state1"></param>
/// <param name="state2"></param>
/// <returns></returns>
public static bool operator !=(PpmState state1, PpmState state2)
{
return state1.Address != state2.Address;
}
/// <summary>
/// Indicates whether this instance and a specified object are equal.
/// </summary>
/// <returns>true if obj and this instance are the same type and represent the same value; otherwise, false.</returns>
/// <param name="obj">Another object to compare to.</param>
public override bool Equals(object obj)
{
if (obj is PpmState)
{
PpmState state = (PpmState)obj;
return state.Address == Address;
}
return base.Equals(obj);
}
/// <summary>
/// Returns the hash code for this instance.
/// </summary>
/// <returns>A 32-bit signed integer that is the hash code for this instance.</returns>
public override int GetHashCode()
{
return Address.GetHashCode();
}
}
}

View File

@@ -1,55 +0,0 @@
#region Using
#endregion
namespace Compress.SevenZip.Compress.PPmd.I1
{
/// <summary>
/// SEE2 (secondary escape estimation) contexts for PPM contexts with masked symbols.
/// </summary>
/// <remarks>
/// <para>
/// This must be a class rather than a structure because MakeEscapeFrequency returns a See2Context
/// instance from the see2Contexts array. The caller (for example, EncodeSymbol2) then updates the
/// returned See2Context instance and expects the updates to be reflected in the see2Contexts array.
/// This would not happen if this were a structure.
/// </para>
/// <remarks>
/// Note that in most cases fields are used rather than properties for performance reasons (for example,
/// <see cref="Shift"/> is a field rather than a property).
/// </remarks>
/// </remarks>
internal class See2Context
{
private const byte PeriodBitCount = 7;
public ushort Summary;
public byte Shift;
public byte Count;
public void Initialize(uint initialValue)
{
Shift = PeriodBitCount - 4;
Summary = (ushort)(initialValue << Shift);
Count = 7;
}
public uint Mean()
{
uint value = (uint)(Summary >> Shift);
Summary = (ushort)(Summary - value);
return (uint)(value + ((value == 0) ? 1 : 0));
}
public void Update()
{
if (Shift < PeriodBitCount && --Count == 0)
{
Summary += Summary;
Count = (byte)(3 << Shift++);
}
}
}
}

View File

@@ -1,81 +0,0 @@
using System;
namespace Compress.SevenZip.Compress.PPmd
{
public enum PpmdVersion
{
H,
H7z,
I1,
}
public class PpmdProperties
{
public PpmdVersion Version = PpmdVersion.I1;
public int ModelOrder;
internal I1.ModelRestorationMethod ModelRestorationMethod;
private int allocatorSize;
internal I1.Allocator Allocator;
public PpmdProperties()
: this(16 << 20, 6)
{
}
public PpmdProperties(int allocatorSize, int modelOrder)
: this(allocatorSize, modelOrder, I1.ModelRestorationMethod.Restart)
{
}
internal PpmdProperties(int allocatorSize, int modelOrder, I1.ModelRestorationMethod modelRestorationMethod)
{
AllocatorSize = allocatorSize;
ModelOrder = modelOrder;
ModelRestorationMethod = modelRestorationMethod;
}
public PpmdProperties(byte[] properties)
{
if (properties.Length == 2)
{
ushort props = BitConverter.ToUInt16(properties, 0);
AllocatorSize = (((props >> 4) & 0xff) + 1) << 20;
ModelOrder = (props & 0x0f) + 1;
ModelRestorationMethod = (I1.ModelRestorationMethod)(props >> 12);
}
else if (properties.Length == 5)
{
Version = PpmdVersion.H7z;
AllocatorSize = BitConverter.ToInt32(properties, 1);
ModelOrder = properties[0];
}
}
public int AllocatorSize
{
get
{
return allocatorSize;
}
set
{
allocatorSize = value;
if (Version == PpmdVersion.I1)
{
if (Allocator == null)
Allocator = new I1.Allocator();
Allocator.Start(allocatorSize);
}
}
}
public byte[] Properties
{
get
{
return BitConverter.GetBytes((ushort)((ModelOrder - 1) + (((AllocatorSize >> 20) - 1) << 4) + ((ushort)ModelRestorationMethod << 12)));
}
}
}
}

View File

@@ -1,154 +0,0 @@
using System;
using System.IO;
using Compress.SevenZip.Compress.RangeCoder;
namespace Compress.SevenZip.Compress.PPmd
{
public class PpmdStream : Stream
{
private PpmdProperties properties;
private Stream stream;
private bool compress;
private I1.Model model;
private H.ModelPPM modelH;
private Decoder decoder;
private long position = 0;
public PpmdStream(PpmdProperties properties, Stream stream, bool compress)
{
this.properties = properties;
this.stream = stream;
this.compress = compress;
if (properties.Version == PpmdVersion.I1)
{
model = new I1.Model();
if (compress)
model.EncodeStart(properties);
else
model.DecodeStart(stream, properties);
}
if (properties.Version == PpmdVersion.H)
{
modelH = new H.ModelPPM();
if (compress)
throw new NotImplementedException();
else
modelH.decodeInit(stream, properties.ModelOrder, properties.AllocatorSize);
}
if (properties.Version == PpmdVersion.H7z)
{
modelH = new H.ModelPPM();
if (compress)
throw new NotImplementedException();
else
modelH.decodeInit(null, properties.ModelOrder, properties.AllocatorSize);
decoder = new Decoder();
decoder.Init(stream);
}
}
public override bool CanRead
{
get { return !compress; }
}
public override bool CanSeek
{
get { return false; }
}
public override bool CanWrite
{
get { return compress; }
}
public override void Flush()
{
}
protected override void Dispose(bool isDisposing)
{
if (isDisposing)
{
if (compress)
model.EncodeBlock(stream, new MemoryStream(), true);
}
base.Dispose(isDisposing);
}
public override long Length
{
get { throw new NotImplementedException(); }
}
public override long Position
{
get
{
return position;
}
set
{
throw new NotImplementedException();
}
}
public override int Read(byte[] buffer, int offset, int count)
{
if (compress)
return 0;
int size = 0;
if (properties.Version == PpmdVersion.I1)
size = model.DecodeBlock(stream, buffer, offset, count);
if (properties.Version == PpmdVersion.H)
{
int c;
while (size < count && (c = modelH.decodeChar()) >= 0)
{
buffer[offset++] = (byte)c;
size++;
}
}
if (properties.Version == PpmdVersion.H7z)
{
int c;
while (size < count && (c = modelH.decodeChar(decoder)) >= 0)
{
buffer[offset++] = (byte)c;
size++;
}
}
position += size;
return size;
}
public override long Seek(long offset, SeekOrigin origin)
{
if (origin != SeekOrigin.Current)
throw new NotImplementedException();
byte[] tmpBuff = new byte[1024];
long sizeToGo = offset;
while (sizeToGo > 0)
{
int sizenow = sizeToGo > 1024 ? 1024 : (int)sizeToGo;
Read(tmpBuff, 0, sizenow);
sizeToGo -= sizenow;
}
return offset;
}
public override void SetLength(long value)
{
throw new NotImplementedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
if (compress)
model.EncodeBlock(stream, new MemoryStream(buffer, offset, count), false);
}
}
}

View File

@@ -1,467 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
namespace Compress.SevenZip.Compress.PPmd
{
internal static class Utility
{
public static ReadOnlyCollection<T> ToReadOnly<T>(this IEnumerable<T> items)
{
return new ReadOnlyCollection<T>(items.ToList());
}
/// <summary>
/// Performs an unsigned bitwise right shift with the specified number
/// </summary>
/// <param name="number">Number to operate on</param>
/// <param name="bits">Ammount of bits to shift</param>
/// <returns>The resulting number from the shift operation</returns>
public static int URShift(int number, int bits)
{
if (number >= 0)
return number >> bits;
else
return (number >> bits) + (2 << ~bits);
}
/// <summary>
/// Performs an unsigned bitwise right shift with the specified number
/// </summary>
/// <param name="number">Number to operate on</param>
/// <param name="bits">Ammount of bits to shift</param>
/// <returns>The resulting number from the shift operation</returns>
public static int URShift(int number, long bits)
{
return URShift(number, (int)bits);
}
/// <summary>
/// Performs an unsigned bitwise right shift with the specified number
/// </summary>
/// <param name="number">Number to operate on</param>
/// <param name="bits">Ammount of bits to shift</param>
/// <returns>The resulting number from the shift operation</returns>
public static long URShift(long number, int bits)
{
if (number >= 0)
return number >> bits;
else
return (number >> bits) + (2L << ~bits);
}
/// <summary>
/// Performs an unsigned bitwise right shift with the specified number
/// </summary>
/// <param name="number">Number to operate on</param>
/// <param name="bits">Ammount of bits to shift</param>
/// <returns>The resulting number from the shift operation</returns>
public static long URShift(long number, long bits)
{
return URShift(number, (int)bits);
}
/// <summary>
/// Fills the array with an specific value from an specific index to an specific index.
/// </summary>
/// <param name="array">The array to be filled.</param>
/// <param name="fromindex">The first index to be filled.</param>
/// <param name="toindex">The last index to be filled.</param>
/// <param name="val">The value to fill the array with.</param>
public static void Fill<T>(T[] array, int fromindex, int toindex, T val) where T : struct
{
if (array.Length == 0)
{
throw new NullReferenceException();
}
if (fromindex > toindex)
{
throw new ArgumentException();
}
if ((fromindex < 0) || ((System.Array)array).Length < toindex)
{
throw new IndexOutOfRangeException();
}
for (int index = (fromindex > 0) ? fromindex-- : fromindex; index < toindex; index++)
{
array[index] = val;
}
}
/// <summary>
/// Fills the array with an specific value.
/// </summary>
/// <param name="array">The array to be filled.</param>
/// <param name="val">The value to fill the array with.</param>
public static void Fill<T>(T[] array, T val) where T : struct
{
Fill(array, 0, array.Length, val);
}
public static void SetSize(this List<byte> list, int count)
{
if (count > list.Count)
{
for (int i = list.Count; i < count; i++)
{
list.Add(0x0);
}
}
else
{
byte[] temp = new byte[count];
list.CopyTo(temp, 0);
list.Clear();
list.AddRange(temp);
}
}
/// <summary> Read a int value from the byte array at the given position (Big Endian)
///
/// </summary>
/// <param name="array">the array to read from
/// </param>
/// <param name="pos">the offset
/// </param>
/// <returns> the value
/// </returns>
public static int readIntBigEndian(byte[] array, int pos)
{
int temp = 0;
temp |= array[pos] & 0xff;
temp <<= 8;
temp |= array[pos + 1] & 0xff;
temp <<= 8;
temp |= array[pos + 2] & 0xff;
temp <<= 8;
temp |= array[pos + 3] & 0xff;
return temp;
}
/// <summary> Read a short value from the byte array at the given position (little
/// Endian)
///
/// </summary>
/// <param name="array">the array to read from
/// </param>
/// <param name="pos">the offset
/// </param>
/// <returns> the value
/// </returns>
public static short readShortLittleEndian(byte[] array, int pos)
{
return BitConverter.ToInt16(array, pos);
}
/// <summary> Read an int value from the byte array at the given position (little
/// Endian)
///
/// </summary>
/// <param name="array">the array to read from
/// </param>
/// <param name="pos">the offset
/// </param>
/// <returns> the value
/// </returns>
public static int readIntLittleEndian(byte[] array, int pos)
{
return BitConverter.ToInt32(array, pos);
}
/// <summary> Write an int value into the byte array at the given position (Big endian)
///
/// </summary>
/// <param name="array">the array
/// </param>
/// <param name="pos">the offset
/// </param>
/// <param name="value">the value to write
/// </param>
public static void writeIntBigEndian(byte[] array, int pos, int value)
{
array[pos] = (byte)((Utility.URShift(value, 24)) & 0xff);
array[pos + 1] = (byte)((Utility.URShift(value, 16)) & 0xff);
array[pos + 2] = (byte)((Utility.URShift(value, 8)) & 0xff);
array[pos + 3] = (byte)((value) & 0xff);
}
/// <summary> Write a short value into the byte array at the given position (little
/// endian)
///
/// </summary>
/// <param name="array">the array
/// </param>
/// <param name="pos">the offset
/// </param>
/// <param name="value">the value to write
/// </param>
public static void WriteLittleEndian(byte[] array, int pos, short value)
{
byte[] newBytes = BitConverter.GetBytes(value);
Array.Copy(newBytes, 0, array, pos, newBytes.Length);
}
/// <summary> Increment a short value at the specified position by the specified amount
/// (little endian).
/// </summary>
public static void incShortLittleEndian(byte[] array, int pos, short incrementValue)
{
short existingValue = BitConverter.ToInt16(array, pos);
existingValue += incrementValue;
WriteLittleEndian(array, pos, existingValue);
//int c = Utility.URShift(((array[pos] & 0xff) + (dv & 0xff)), 8);
//array[pos] = (byte)(array[pos] + (dv & 0xff));
//if ((c > 0) || ((dv & 0xff00) != 0))
//{
// array[pos + 1] = (byte)(array[pos + 1] + ((Utility.URShift(dv, 8)) & 0xff) + c);
//}
}
/// <summary> Write an int value into the byte array at the given position (little
/// endian)
///
/// </summary>
/// <param name="array">the array
/// </param>
/// <param name="pos">the offset
/// </param>
/// <param name="value">the value to write
/// </param>
public static void WriteLittleEndian(byte[] array, int pos, int value)
{
byte[] newBytes = BitConverter.GetBytes(value);
Array.Copy(newBytes, 0, array, pos, newBytes.Length);
}
public static void Initialize<T>(this T[] array, Func<T> func)
{
for (int i = 0; i < array.Length; i++)
{
array[i] = func();
}
}
public static void AddRange<T>(this ICollection<T> destination, IEnumerable<T> source)
{
foreach (T item in source)
{
destination.Add(item);
}
}
public static void ForEach<T>(this IEnumerable<T> items, Action<T> action)
{
foreach (T item in items)
{
action(item);
}
}
public static IEnumerable<T> AsEnumerable<T>(this T item)
{
yield return item;
}
public static void CheckNotNull(this object obj, string name)
{
if (obj == null)
{
throw new ArgumentNullException(name);
}
}
public static void CheckNotNullOrEmpty(this string obj, string name)
{
obj.CheckNotNull(name);
if (obj.Length == 0)
{
throw new ArgumentException("String is empty.");
}
}
public static void Skip(this Stream source, long advanceAmount)
{
byte[] buffer = new byte[32 * 1024];
int read = 0;
int readCount = 0;
do
{
readCount = buffer.Length;
if (readCount > advanceAmount)
{
readCount = (int)advanceAmount;
}
read = source.Read(buffer, 0, readCount);
if (read < 0)
{
break;
}
advanceAmount -= read;
if (advanceAmount == 0)
{
break;
}
} while (true);
}
public static void SkipAll(this Stream source)
{
byte[] buffer = new byte[32 * 1024];
do
{
} while (source.Read(buffer, 0, buffer.Length) == buffer.Length);
}
public static byte[] UInt32ToBigEndianBytes(uint x)
{
return new byte[] {
(byte)((x >> 24) & 0xff),
(byte)((x >> 16) & 0xff),
(byte)((x >> 8) & 0xff),
(byte)(x & 0xff) };
}
public static DateTime DosDateToDateTime(UInt16 iDate, UInt16 iTime)
{
int year = iDate / 512 + 1980;
int month = iDate % 512 / 32;
int day = iDate % 512 % 32;
int hour = iTime / 2048;
int minute = iTime % 2048 / 32;
int second = iTime % 2048 % 32 * 2;
if (iDate == UInt16.MaxValue || month == 0 || day == 0)
{
year = 1980;
month = 1;
day = 1;
}
if (iTime == UInt16.MaxValue)
{
hour = minute = second = 0;
}
DateTime dt;
try
{
dt = new DateTime(year, month, day, hour, minute, second);
}
catch
{
dt = new DateTime();
}
return dt;
}
public static uint DateTimeToDosTime(this DateTime? dateTime)
{
if (dateTime == null)
{
return 0;
}
return (uint)(
(dateTime.Value.Second / 2) | (dateTime.Value.Minute << 5) | (dateTime.Value.Hour << 11) |
(dateTime.Value.Day << 16) | (dateTime.Value.Month << 21) | ((dateTime.Value.Year - 1980) << 25));
}
public static DateTime DosDateToDateTime(UInt32 iTime)
{
return DosDateToDateTime((UInt16)(iTime / 65536),
(UInt16)(iTime % 65536));
}
public static DateTime DosDateToDateTime(Int32 iTime)
{
return DosDateToDateTime((UInt32)iTime);
}
public static long TransferTo(this Stream source, Stream destination)
{
byte[] array = new byte[4096];
int count;
long total = 0;
while ((count = source.Read(array, 0, array.Length)) != 0)
{
total += count;
destination.Write(array, 0, count);
}
return total;
}
public static bool ReadFully(this Stream stream, byte[] buffer)
{
int total = 0;
int read;
while ((read = stream.Read(buffer, total, buffer.Length - total)) > 0)
{
total += read;
if (total >= buffer.Length)
{
return true;
}
}
return (total >= buffer.Length);
}
public static string TrimNulls(this string source)
{
return source.Replace('\0', ' ').Trim();
}
public static bool BinaryEquals(this byte[] source, byte[] target)
{
if (source.Length != target.Length)
{
return false;
}
for (int i = 0; i < source.Length; ++i)
{
if (source[i] != target[i])
{
return false;
}
}
return true;
}
#if PORTABLE
public static void CopyTo(this byte[] array, byte[] destination, int index)
{
Array.Copy(array, 0, destination, index, array.Length);
}
public static long HostToNetworkOrder(long host)
{
return (int)((long)HostToNetworkOrder((int)host)
& unchecked((long)(unchecked((ulong)-1))) << 32
| ((long)HostToNetworkOrder((int)((int)host >> 32)) & unchecked((long)(unchecked((ulong)-1)))));
}
public static int HostToNetworkOrder(int host)
{
return (int)((int)(HostToNetworkOrder((short)host) & -1) << 16 | (HostToNetworkOrder((short)(host >> 16)) & -1));
}
public static short HostToNetworkOrder(short host)
{
return (short)((int)(host & 255) << 8 | ((int)host >> 8 & 255));
}
public static long NetworkToHostOrder(long network)
{
return HostToNetworkOrder(network);
}
public static int NetworkToHostOrder(int network)
{
return HostToNetworkOrder(network);
}
public static short NetworkToHostOrder(short network)
{
return HostToNetworkOrder(network);
}
#endif
}
}

View File

@@ -1,247 +0,0 @@
using System;
namespace Compress.SevenZip.Compress.RangeCoder
{
internal class Encoder
{
public const uint kTopValue = (1 << 24);
System.IO.Stream Stream;
public UInt64 Low;
public uint Range;
uint _cacheSize;
byte _cache;
//long StartPosition;
public void SetStream(System.IO.Stream stream)
{
Stream = stream;
}
public void ReleaseStream()
{
Stream = null;
}
public void Init()
{
//StartPosition = Stream.Position;
Low = 0;
Range = 0xFFFFFFFF;
_cacheSize = 1;
_cache = 0;
}
public void FlushData()
{
for (int i = 0; i < 5; i++)
ShiftLow();
}
public void FlushStream()
{
Stream.Flush();
}
public void CloseStream()
{
Stream.Dispose();
}
public void Encode(uint start, uint size, uint total)
{
Low += start * (Range /= total);
Range *= size;
while (Range < kTopValue)
{
Range <<= 8;
ShiftLow();
}
}
public void ShiftLow()
{
if ((uint)Low < (uint)0xFF000000 || (uint)(Low >> 32) == 1)
{
byte temp = _cache;
do
{
Stream.WriteByte((byte)(temp + (Low >> 32)));
temp = 0xFF;
}
while (--_cacheSize != 0);
_cache = (byte)(((uint)Low) >> 24);
}
_cacheSize++;
Low = ((uint)Low) << 8;
}
public void EncodeDirectBits(uint v, int numTotalBits)
{
for (int i = numTotalBits - 1; i >= 0; i--)
{
Range >>= 1;
if (((v >> i) & 1) == 1)
Low += Range;
if (Range < kTopValue)
{
Range <<= 8;
ShiftLow();
}
}
}
public void EncodeBit(uint size0, int numTotalBits, uint symbol)
{
uint newBound = (Range >> numTotalBits) * size0;
if (symbol == 0)
Range = newBound;
else
{
Low += newBound;
Range -= newBound;
}
while (Range < kTopValue)
{
Range <<= 8;
ShiftLow();
}
}
public long GetProcessedSizeAdd()
{
return -1;
//return _cacheSize + Stream.Position - StartPosition + 4;
// (long)Stream.GetProcessedSize();
}
}
internal class Decoder
{
public const uint kTopValue = (1 << 24);
public uint Range;
public uint Code = 0;
// public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16);
public System.IO.Stream Stream;
public long Total;
public void Init(System.IO.Stream stream)
{
// Stream.Init(stream);
Stream = stream;
Code = 0;
Range = 0xFFFFFFFF;
for (int i = 0; i < 5; i++)
Code = (Code << 8) | (byte)Stream.ReadByte();
Total = 5;
}
public void ReleaseStream()
{
// Stream.ReleaseStream();
Stream = null;
}
public void CloseStream()
{
Stream.Dispose();
}
public void Normalize()
{
while (Range < kTopValue)
{
Code = (Code << 8) | (byte)Stream.ReadByte();
Range <<= 8;
Total++;
}
}
public void Normalize2()
{
if (Range < kTopValue)
{
Code = (Code << 8) | (byte)Stream.ReadByte();
Range <<= 8;
Total++;
}
}
public uint GetThreshold(uint total)
{
return Code / (Range /= total);
}
public void Decode(uint start, uint size)
{
Code -= start * Range;
Range *= size;
Normalize();
}
public uint DecodeDirectBits(int numTotalBits)
{
uint range = Range;
uint code = Code;
uint result = 0;
for (int i = numTotalBits; i > 0; i--)
{
range >>= 1;
/*
result <<= 1;
if (code >= range)
{
code -= range;
result |= 1;
}
*/
uint t = (code - range) >> 31;
code -= range & (t - 1);
result = (result << 1) | (1 - t);
if (range < kTopValue)
{
code = (code << 8) | (byte)Stream.ReadByte();
range <<= 8;
Total++;
}
}
Range = range;
Code = code;
return result;
}
public uint DecodeBit(uint size0, int numTotalBits)
{
uint newBound = (Range >> numTotalBits) * size0;
uint symbol;
if (Code < newBound)
{
symbol = 0;
Range = newBound;
}
else
{
symbol = 1;
Code -= newBound;
Range -= newBound;
}
Normalize();
return symbol;
}
public bool IsFinished
{
get
{
return Code == 0;
}
}
// ulong GetProcessedSize() {return Stream.GetProcessedSize(); }
}
}

View File

@@ -1,119 +0,0 @@
using System;
namespace Compress.SevenZip.Compress.RangeCoder
{
internal struct BitEncoder
{
public const int kNumBitModelTotalBits = 11;
public const uint kBitModelTotal = (1 << kNumBitModelTotalBits);
const int kNumMoveBits = 5;
const int kNumMoveReducingBits = 2;
public const int kNumBitPriceShiftBits = 6;
uint Prob;
public void Init() { Prob = kBitModelTotal >> 1; }
public void UpdateModel(uint symbol)
{
if (symbol == 0)
Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
else
Prob -= (Prob) >> kNumMoveBits;
}
public void Encode(Encoder encoder, uint symbol)
{
// encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol);
// UpdateModel(symbol);
uint newBound = (encoder.Range >> kNumBitModelTotalBits) * Prob;
if (symbol == 0)
{
encoder.Range = newBound;
Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
}
else
{
encoder.Low += newBound;
encoder.Range -= newBound;
Prob -= (Prob) >> kNumMoveBits;
}
if (encoder.Range < Encoder.kTopValue)
{
encoder.Range <<= 8;
encoder.ShiftLow();
}
}
private static UInt32[] ProbPrices = new UInt32[kBitModelTotal >> kNumMoveReducingBits];
static BitEncoder()
{
const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits);
for (int i = kNumBits - 1; i >= 0; i--)
{
UInt32 start = (UInt32)1 << (kNumBits - i - 1);
UInt32 end = (UInt32)1 << (kNumBits - i);
for (UInt32 j = start; j < end; j++)
ProbPrices[j] = ((UInt32)i << kNumBitPriceShiftBits) +
(((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1));
}
}
public uint GetPrice(uint symbol)
{
return ProbPrices[(((Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits];
}
public uint GetPrice0() { return ProbPrices[Prob >> kNumMoveReducingBits]; }
public uint GetPrice1() { return ProbPrices[(kBitModelTotal - Prob) >> kNumMoveReducingBits]; }
}
internal struct BitDecoder
{
public const int kNumBitModelTotalBits = 11;
public const uint kBitModelTotal = (1 << kNumBitModelTotalBits);
const int kNumMoveBits = 5;
uint Prob;
public void UpdateModel(int numMoveBits, uint symbol)
{
if (symbol == 0)
Prob += (kBitModelTotal - Prob) >> numMoveBits;
else
Prob -= (Prob) >> numMoveBits;
}
public void Init() { Prob = kBitModelTotal >> 1; }
public uint Decode(RangeCoder.Decoder rangeDecoder)
{
uint newBound = (uint)(rangeDecoder.Range >> kNumBitModelTotalBits) * (uint)Prob;
if (rangeDecoder.Code < newBound)
{
rangeDecoder.Range = newBound;
Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
if (rangeDecoder.Range < Decoder.kTopValue)
{
rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte();
rangeDecoder.Range <<= 8;
rangeDecoder.Total++;
}
return 0;
}
else
{
rangeDecoder.Range -= newBound;
rangeDecoder.Code -= newBound;
Prob -= (Prob) >> kNumMoveBits;
if (rangeDecoder.Range < Decoder.kTopValue)
{
rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte();
rangeDecoder.Range <<= 8;
rangeDecoder.Total++;
}
return 1;
}
}
}
}

View File

@@ -1,157 +0,0 @@
using System;
namespace Compress.SevenZip.Compress.RangeCoder
{
internal struct BitTreeEncoder
{
BitEncoder[] Models;
int NumBitLevels;
public BitTreeEncoder(int numBitLevels)
{
NumBitLevels = numBitLevels;
Models = new BitEncoder[1 << numBitLevels];
}
public void Init()
{
for (uint i = 1; i < (1 << NumBitLevels); i++)
Models[i].Init();
}
public void Encode(Encoder rangeEncoder, UInt32 symbol)
{
UInt32 m = 1;
for (int bitIndex = NumBitLevels; bitIndex > 0;)
{
bitIndex--;
UInt32 bit = (symbol >> bitIndex) & 1;
Models[m].Encode(rangeEncoder, bit);
m = (m << 1) | bit;
}
}
public void ReverseEncode(Encoder rangeEncoder, UInt32 symbol)
{
UInt32 m = 1;
for (UInt32 i = 0; i < NumBitLevels; i++)
{
UInt32 bit = symbol & 1;
Models[m].Encode(rangeEncoder, bit);
m = (m << 1) | bit;
symbol >>= 1;
}
}
public UInt32 GetPrice(UInt32 symbol)
{
UInt32 price = 0;
UInt32 m = 1;
for (int bitIndex = NumBitLevels; bitIndex > 0;)
{
bitIndex--;
UInt32 bit = (symbol >> bitIndex) & 1;
price += Models[m].GetPrice(bit);
m = (m << 1) + bit;
}
return price;
}
public UInt32 ReverseGetPrice(UInt32 symbol)
{
UInt32 price = 0;
UInt32 m = 1;
for (int i = NumBitLevels; i > 0; i--)
{
UInt32 bit = symbol & 1;
symbol >>= 1;
price += Models[m].GetPrice(bit);
m = (m << 1) | bit;
}
return price;
}
public static UInt32 ReverseGetPrice(BitEncoder[] Models, UInt32 startIndex,
int NumBitLevels, UInt32 symbol)
{
UInt32 price = 0;
UInt32 m = 1;
for (int i = NumBitLevels; i > 0; i--)
{
UInt32 bit = symbol & 1;
symbol >>= 1;
price += Models[startIndex + m].GetPrice(bit);
m = (m << 1) | bit;
}
return price;
}
public static void ReverseEncode(BitEncoder[] Models, UInt32 startIndex,
Encoder rangeEncoder, int NumBitLevels, UInt32 symbol)
{
UInt32 m = 1;
for (int i = 0; i < NumBitLevels; i++)
{
UInt32 bit = symbol & 1;
Models[startIndex + m].Encode(rangeEncoder, bit);
m = (m << 1) | bit;
symbol >>= 1;
}
}
}
internal struct BitTreeDecoder
{
BitDecoder[] Models;
int NumBitLevels;
public BitTreeDecoder(int numBitLevels)
{
NumBitLevels = numBitLevels;
Models = new BitDecoder[1 << numBitLevels];
}
public void Init()
{
for (uint i = 1; i < (1 << NumBitLevels); i++)
Models[i].Init();
}
public uint Decode(RangeCoder.Decoder rangeDecoder)
{
uint m = 1;
for (int bitIndex = NumBitLevels; bitIndex > 0; bitIndex--)
m = (m << 1) + Models[m].Decode(rangeDecoder);
return m - ((uint)1 << NumBitLevels);
}
public uint ReverseDecode(RangeCoder.Decoder rangeDecoder)
{
uint m = 1;
uint symbol = 0;
for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
{
uint bit = Models[m].Decode(rangeDecoder);
m <<= 1;
m += bit;
symbol |= (bit << bitIndex);
}
return symbol;
}
public static uint ReverseDecode(BitDecoder[] Models, UInt32 startIndex,
RangeCoder.Decoder rangeDecoder, int NumBitLevels)
{
uint m = 1;
uint symbol = 0;
for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
{
uint bit = Models[startIndex + m].Decode(rangeDecoder);
m <<= 1;
m += bit;
symbol |= (bit << bitIndex);
}
return symbol;
}
}
}

View File

@@ -1,194 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using Interop = Zstandard.Net.ZstandardInterop;
namespace Zstandard.Net
{
/// <summary>
/// A Zstandard dictionary improves the compression ratio and speed on small data dramatically.
/// </summary>
/// <remarks>
/// A Zstandard dictionary is calculated with a high number of small sample data.
/// Please refer to the Zstandard documentation for more details.
/// </remarks>
/// <seealso cref="System.IDisposable" />
public sealed class ZstandardDictionary : IDisposable
{
private byte[] dictionary;
private IntPtr ddict;
private Dictionary<int, IntPtr> cdicts = new Dictionary<int, IntPtr>();
private object lockObject = new object();
private bool isDisposed = false;
/// <summary>
/// Initializes a new instance of the <see cref="ZstandardDictionary"/> class.
/// </summary>
/// <param name="dictionary">The dictionary raw data.</param>
public ZstandardDictionary(byte[] dictionary)
{
this.dictionary = dictionary;
}
/// <summary>
/// Initializes a new instance of the <see cref="ZstandardDictionary"/> class.
/// </summary>
/// <param name="dictionaryPath">The dictionary path.</param>
public ZstandardDictionary(string dictionaryPath)
{
this.dictionary = File.ReadAllBytes(dictionaryPath);
}
/// <summary>
/// Initializes a new instance of the <see cref="ZstandardDictionary"/> class.
/// </summary>
/// <param name="dictionaryStream">The dictionary stream.</param>
public ZstandardDictionary(Stream dictionaryStream)
{
using (var memoryStream = new MemoryStream())
{
dictionaryStream.CopyTo(memoryStream);
this.dictionary = memoryStream.ToArray();
}
}
/// <summary>
/// Finalizes an instance of the <see cref="ZstandardDictionary"/> class.
/// </summary>
~ZstandardDictionary()
{
this.Dispose(false);
}
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Releases unmanaged resources.
/// </summary>
/// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
private void Dispose(bool dispose)
{
if (this.isDisposed == false)
{
this.isDisposed = true;
if (this.ddict != IntPtr.Zero)
{
Interop.ZSTD_freeDDict(this.ddict);
this.ddict = IntPtr.Zero;
}
foreach (var kv in this.cdicts.ToList())
{
Interop.ZSTD_freeCDict(kv.Value);
this.cdicts.Remove(kv.Key);
}
}
}
/// <summary>
/// Gets the compression dictionary for the specified compression level.
/// </summary>
/// <param name="compressionLevel">The compression level.</param>
/// <returns>
/// The IntPtr to the compression dictionary.
/// </returns>
/// <exception cref="ObjectDisposedException">ZstandardDictionary</exception>
internal IntPtr GetCompressionDictionary(int compressionLevel)
{
if (this.isDisposed)
{
throw new ObjectDisposedException(nameof(ZstandardDictionary));
}
lock (this.lockObject)
{
if (this.cdicts.TryGetValue(compressionLevel, out var cdict) == false)
{
this.cdicts[compressionLevel] = cdict = this.CreateCompressionDictionary(compressionLevel);
}
return cdict;
}
}
/// <summary>
/// Gets the decompression dictionary.
/// </summary>
/// <returns>
/// The IntPtr to the decompression dictionary.
/// </returns>
/// <exception cref="ObjectDisposedException">ZstandardDictionary</exception>
internal IntPtr GetDecompressionDictionary()
{
if (this.isDisposed)
{
throw new ObjectDisposedException(nameof(ZstandardDictionary));
}
lock (this.lockObject)
{
if (this.ddict == IntPtr.Zero)
{
this.ddict = this.CreateDecompressionDictionary();
}
return this.ddict;
}
}
/// <summary>
/// Creates a new compression dictionary.
/// </summary>
/// <param name="compressionLevel">The compression level.</param>
/// <returns>
/// The IntPtr to the compression dictionary.
/// </returns>
private IntPtr CreateCompressionDictionary(int compressionLevel)
{
var alloc = GCHandle.Alloc(this.dictionary, GCHandleType.Pinned);
try
{
var dictBuffer = Marshal.UnsafeAddrOfPinnedArrayElement(this.dictionary, 0);
var dictSize = new UIntPtr((uint)this.dictionary.Length);
return Interop.ZSTD_createCDict(dictBuffer, dictSize, compressionLevel);
}
finally
{
alloc.Free();
}
}
/// <summary>
/// Creates a new decompression dictionary.
/// </summary>
/// <returns>
/// The IntPtr to the decompression dictionary.
/// </returns>
private IntPtr CreateDecompressionDictionary()
{
var alloc = GCHandle.Alloc(this.dictionary, GCHandleType.Pinned);
try
{
var dictBuffer = Marshal.UnsafeAddrOfPinnedArrayElement(this.dictionary, 0);
var dictSize = new UIntPtr((uint)this.dictionary.Length);
return Interop.ZSTD_createDDict(dictBuffer, dictSize);
}
finally
{
alloc.Free();
}
}
}
}

View File

@@ -1,143 +0,0 @@
using System;
using System.IO;
using System.Runtime.InteropServices;
namespace Zstandard.Net
{
internal static class ZstandardInterop
{
static ZstandardInterop()
{
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
{
var root = Path.GetDirectoryName(typeof(ZstandardInterop).Assembly.Location);
var path = Environment.Is64BitProcess ? "x64" : "x86";
var file = Path.Combine(root, path, "libzstd.dll");
LoadLibraryEx(file, IntPtr.Zero, LoadLibraryFlags.LOAD_LIBRARY_SEARCH_APPLICATION_DIR);
}
}
[StructLayout(LayoutKind.Sequential)]
public class Buffer
{
public IntPtr Data = IntPtr.Zero;
public UIntPtr Size = UIntPtr.Zero;
public UIntPtr Position = UIntPtr.Zero;
}
public static void ThrowIfError(UIntPtr code)
{
if (ZSTD_isError(code))
{
var errorPtr = ZSTD_getErrorName(code);
var errorMsg = Marshal.PtrToStringAnsi(errorPtr);
throw new IOException(errorMsg);
}
}
//-----------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------
[Flags]
private enum LoadLibraryFlags : uint
{
DONT_RESOLVE_DLL_REFERENCES = 0x00000001,
LOAD_IGNORE_CODE_AUTHZ_LEVEL = 0x00000010,
LOAD_LIBRARY_AS_DATAFILE = 0x00000002,
LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE = 0x00000040,
LOAD_LIBRARY_AS_IMAGE_RESOURCE = 0x00000020,
LOAD_LIBRARY_SEARCH_APPLICATION_DIR = 0x00000200,
LOAD_LIBRARY_SEARCH_DEFAULT_DIRS = 0x00001000,
LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR = 0x00000100,
LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800,
LOAD_LIBRARY_SEARCH_USER_DIRS = 0x00000400,
LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008
}
[DllImport("kernel32", SetLastError = true)]
private static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hReservedNull, LoadLibraryFlags dwFlags);
//-----------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------
[DllImport("libzstd", CallingConvention = CallingConvention.Cdecl)]
public static extern uint ZSTD_versionNumber();
[DllImport("libzstd", CallingConvention = CallingConvention.Cdecl)]
public static extern int ZSTD_maxCLevel();
//-----------------------------------------------------------------------------------------
[DllImport("libzstd", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr ZSTD_createCStream();
[DllImport("libzstd", CallingConvention = CallingConvention.Cdecl)]
public static extern UIntPtr ZSTD_initCStream(IntPtr zcs, int compressionLevel);
[DllImport("libzstd", CallingConvention = CallingConvention.Cdecl)]
public static extern UIntPtr ZSTD_freeCStream(IntPtr zcs);
[DllImport("libzstd", CallingConvention = CallingConvention.Cdecl)]
public static extern UIntPtr ZSTD_CStreamInSize();
[DllImport("libzstd", CallingConvention = CallingConvention.Cdecl)]
public static extern UIntPtr ZSTD_CStreamOutSize();
[DllImport("libzstd", CallingConvention = CallingConvention.Cdecl)]
public static extern UIntPtr ZSTD_compressStream(IntPtr zcs, [MarshalAs(UnmanagedType.LPStruct)] Buffer outputBuffer, [MarshalAs(UnmanagedType.LPStruct)] Buffer inputBuffer);
[DllImport("libzstd", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr ZSTD_createCDict(IntPtr dictBuffer, UIntPtr dictSize, int compressionLevel);
[DllImport("libzstd", CallingConvention = CallingConvention.Cdecl)]
public static extern UIntPtr ZSTD_freeCDict(IntPtr cdict);
[DllImport("libzstd", CallingConvention = CallingConvention.Cdecl)]
public static extern UIntPtr ZSTD_initCStream_usingCDict(IntPtr zcs, IntPtr cdict);
//-----------------------------------------------------------------------------------------
[DllImport("libzstd", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr ZSTD_createDStream();
[DllImport("libzstd", CallingConvention = CallingConvention.Cdecl)]
public static extern UIntPtr ZSTD_initDStream(IntPtr zds);
[DllImport("libzstd", CallingConvention = CallingConvention.Cdecl)]
public static extern UIntPtr ZSTD_freeDStream(IntPtr zds);
[DllImport("libzstd", CallingConvention = CallingConvention.Cdecl)]
public static extern UIntPtr ZSTD_DStreamInSize();
[DllImport("libzstd", CallingConvention = CallingConvention.Cdecl)]
public static extern UIntPtr ZSTD_DStreamOutSize();
[DllImport("libzstd", CallingConvention = CallingConvention.Cdecl)]
public static extern UIntPtr ZSTD_decompressStream(IntPtr zds, [MarshalAs(UnmanagedType.LPStruct)] Buffer outputBuffer, [MarshalAs(UnmanagedType.LPStruct)] Buffer inputBuffer);
[DllImport("libzstd", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr ZSTD_createDDict(IntPtr dictBuffer, UIntPtr dictSize);
[DllImport("libzstd", CallingConvention = CallingConvention.Cdecl)]
public static extern UIntPtr ZSTD_freeDDict(IntPtr ddict);
[DllImport("libzstd", CallingConvention = CallingConvention.Cdecl)]
public static extern UIntPtr ZSTD_initDStream_usingDDict(IntPtr zds, IntPtr ddict);
//-----------------------------------------------------------------------------------------
[DllImport("libzstd", CallingConvention = CallingConvention.Cdecl)]
public static extern UIntPtr ZSTD_flushStream(IntPtr zcs, [MarshalAs(UnmanagedType.LPStruct)] Buffer outputBuffer);
[DllImport("libzstd", CallingConvention = CallingConvention.Cdecl)]
public static extern UIntPtr ZSTD_endStream(IntPtr zcs, [MarshalAs(UnmanagedType.LPStruct)] Buffer outputBuffer);
//-----------------------------------------------------------------------------------------
[DllImport("libzstd", CallingConvention = CallingConvention.Cdecl)]
internal static extern bool ZSTD_isError(UIntPtr code);
[DllImport("libzstd", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr ZSTD_getErrorName(UIntPtr code);
}
}

View File

@@ -1,398 +0,0 @@
using System;
using System.IO;
using System.IO.Compression;
using System.Runtime.InteropServices;
using Interop = Zstandard.Net.ZstandardInterop;
namespace Zstandard.Net
{
/// <summary>
/// Provides methods and properties for compressing and decompressing streams by using the Zstandard algorithm.
/// </summary>
public class ZstandardStream : Stream
{
private Stream stream;
private CompressionMode mode;
private Boolean leaveOpen;
private Boolean isClosed = false;
private Boolean isDisposed = false;
private Boolean isInitialized = false;
private IntPtr zstream;
private uint zstreamInputSize;
private uint zstreamOutputSize;
private byte[] data;
private bool dataDepleted = false;
private bool dataSkipRead = false;
private int dataPosition = 0;
private int dataSize = 0;
private long position = 0;
private Interop.Buffer outputBuffer = new Interop.Buffer();
private Interop.Buffer inputBuffer = new Interop.Buffer();
/// <summary>
/// Initializes a new instance of the <see cref="ZstandardStream"/> class by using the specified stream and compression mode, and optionally leaves the stream open.
/// </summary>
/// <param name="stream">The stream to compress.</param>
/// <param name="mode">One of the enumeration values that indicates whether to compress or decompress the stream.</param>
/// <param name="leaveOpen">true to leave the stream open after disposing the <see cref="ZstandardStream"/> object; otherwise, false.</param>
public ZstandardStream(Stream stream, CompressionMode mode, bool leaveOpen = false)
{
this.stream = stream ?? throw new ArgumentNullException(nameof(stream));
this.mode = mode;
this.leaveOpen = leaveOpen;
position = 0;
if (mode == CompressionMode.Compress)
{
this.zstreamInputSize = Interop.ZSTD_CStreamInSize().ToUInt32();
this.zstreamOutputSize = Interop.ZSTD_CStreamOutSize().ToUInt32();
this.zstream = Interop.ZSTD_createCStream();
this.data = new byte[(int)this.zstreamOutputSize];
}
if (mode == CompressionMode.Decompress)
{
this.zstreamInputSize = Interop.ZSTD_DStreamInSize().ToUInt32();
this.zstreamOutputSize = Interop.ZSTD_DStreamOutSize().ToUInt32();
this.zstream = Interop.ZSTD_createDStream();
this.data = new byte[(int)this.zstreamInputSize];
}
}
/// <summary>
/// Initializes a new instance of the <see cref="ZstandardStream"/> class by using the specified stream and compression level, and optionally leaves the stream open.
/// </summary>
/// <param name="stream">The stream to compress.</param>
/// <param name="compressionLevel">The compression level.</param>
/// <param name="leaveOpen">true to leave the stream open after disposing the <see cref="ZstandardStream"/> object; otherwise, false.</param>
public ZstandardStream(Stream stream, int compressionLevel, bool leaveOpen = false) : this(stream, CompressionMode.Compress, leaveOpen)
{
this.CompressionLevel = compressionLevel;
}
//-----------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------
/// <summary>
/// The version of the native Zstd library.
/// </summary>
public static Version Version
{
get
{
var version = (int)Interop.ZSTD_versionNumber();
return new Version((version / 10000) % 100, (version / 100) % 100, version % 100);
}
}
/// <summary>
/// The maximum compression level supported by the native Zstd library.
/// </summary>
public static int MaxCompressionLevel
{
get
{
return Interop.ZSTD_maxCLevel();
}
}
//-----------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------
/// <summary>
/// Gets or sets the compression level to use, the default is 6.
/// </summary>
/// <remarks>
/// To get the maximum compression level see <see cref="MaxCompressionLevel"/>.
/// </remarks>
public int CompressionLevel { get; set; } = 6;
/// <summary>
/// Gets or sets the compression dictionary tp use, the default is null.
/// </summary>
/// <value>
/// The compression dictionary.
/// </value>
public ZstandardDictionary CompressionDictionary { get; set; } = null;
/// <summary>
/// Gets whether the current stream supports reading.
/// </summary>
public override bool CanRead => this.stream.CanRead && this.mode == CompressionMode.Decompress;
/// <summary>
/// Gets whether the current stream supports writing.
/// </summary>
public override bool CanWrite => this.stream.CanWrite && this.mode == CompressionMode.Compress;
/// <summary>
/// Gets whether the current stream supports seeking.
/// </summary>
public override bool CanSeek => false;
/// <summary>
/// Gets the length in bytes of the stream.
/// </summary>
public override long Length => throw new NotSupportedException();
/// <summary>
/// Gets or sets the position within the current stream.
/// </summary>
public override long Position
{
get => position;
set => throw new NotSupportedException();
}
//-----------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (this.isDisposed == false)
{
if (!this.isClosed) ReleaseResources(flushStream: false);
this.isDisposed = true;
this.data = null;
}
}
public override void Close()
{
if (this.isClosed) return;
try
{
ReleaseResources(flushStream: true);
}
finally
{
this.isClosed = true;
base.Close();
}
}
private void ReleaseResources(bool flushStream)
{
if (this.mode == CompressionMode.Compress)
{
try
{
if (flushStream)
{
this.ProcessStream((zcs, buffer) => Interop.ThrowIfError(Interop.ZSTD_flushStream(zcs, buffer)));
this.ProcessStream((zcs, buffer) => Interop.ThrowIfError(Interop.ZSTD_endStream(zcs, buffer)));
this.stream.Flush();
}
}
finally
{
Interop.ZSTD_freeCStream(this.zstream);
if (!this.leaveOpen) this.stream.Close();
}
}
else if (this.mode == CompressionMode.Decompress)
{
Interop.ZSTD_freeDStream(this.zstream);
if (!this.leaveOpen) this.stream.Close();
}
}
public override void Flush()
{
if (this.mode == CompressionMode.Compress)
{
this.ProcessStream((zcs, buffer) => Interop.ThrowIfError(Interop.ZSTD_flushStream(zcs, buffer)));
this.stream.Flush();
}
}
public override int Read(byte[] buffer, int offset, int count)
{
if (this.CanRead == false) throw new NotSupportedException();
// prevent the buffers from being moved around by the garbage collector
var alloc1 = GCHandle.Alloc(buffer, GCHandleType.Pinned);
var alloc2 = GCHandle.Alloc(this.data, GCHandleType.Pinned);
try
{
var length = 0;
if (this.isInitialized == false)
{
this.isInitialized = true;
var result = this.CompressionDictionary == null
? Interop.ZSTD_initDStream(this.zstream)
: Interop.ZSTD_initDStream_usingDDict(this.zstream, this.CompressionDictionary.GetDecompressionDictionary());
}
while (count > 0)
{
var inputSize = this.dataSize - this.dataPosition;
// read data from input stream
if (inputSize <= 0 && !this.dataDepleted && !this.dataSkipRead)
{
this.dataSize = this.stream.Read(this.data, 0, (int)this.zstreamInputSize);
this.dataDepleted = this.dataSize <= 0;
this.dataPosition = 0;
inputSize = this.dataDepleted ? 0 : this.dataSize;
// skip stream.Read until the internal buffer is depleted
// avoids a Read timeout for applications that know the exact number of bytes in the stream
this.dataSkipRead = true;
}
// configure the inputBuffer
this.inputBuffer.Data = inputSize <= 0 ? IntPtr.Zero : Marshal.UnsafeAddrOfPinnedArrayElement(this.data, this.dataPosition);
this.inputBuffer.Size = inputSize <= 0 ? UIntPtr.Zero : new UIntPtr((uint)inputSize);
this.inputBuffer.Position = UIntPtr.Zero;
// configure the outputBuffer
this.outputBuffer.Data = Marshal.UnsafeAddrOfPinnedArrayElement(buffer, offset);
this.outputBuffer.Size = new UIntPtr((uint)count);
this.outputBuffer.Position = UIntPtr.Zero;
// decompress inputBuffer to outputBuffer
Interop.ThrowIfError(Interop.ZSTD_decompressStream(this.zstream, this.outputBuffer, this.inputBuffer));
// calculate progress in outputBuffer
var outputBufferPosition = (int)this.outputBuffer.Position.ToUInt32();
if (outputBufferPosition == 0)
{
// the internal buffer is depleted, we're either done
if (this.dataDepleted) break;
// or we need more bytes
this.dataSkipRead = false;
}
length += outputBufferPosition;
offset += outputBufferPosition;
count -= outputBufferPosition;
// calculate progress in inputBuffer
var inputBufferPosition = (int)inputBuffer.Position.ToUInt32();
this.dataPosition += inputBufferPosition;
}
position += length;
return length;
}
finally
{
alloc1.Free();
alloc2.Free();
}
}
public override void Write(byte[] buffer, int offset, int count)
{
if (this.CanWrite == false) throw new NotSupportedException();
// prevent the buffers from being moved around by the garbage collector
var alloc1 = GCHandle.Alloc(buffer, GCHandleType.Pinned);
var alloc2 = GCHandle.Alloc(this.data, GCHandleType.Pinned);
try
{
if (this.isInitialized == false)
{
this.isInitialized = true;
var result = this.CompressionDictionary == null
? Interop.ZSTD_initCStream(this.zstream, this.CompressionLevel)
: Interop.ZSTD_initCStream_usingCDict(this.zstream, this.CompressionDictionary.GetCompressionDictionary(this.CompressionLevel));
Interop.ThrowIfError(result);
}
while (count > 0)
{
var inputSize = Math.Min((uint)count, this.zstreamInputSize);
// configure the outputBuffer
this.outputBuffer.Data = Marshal.UnsafeAddrOfPinnedArrayElement(this.data, 0);
this.outputBuffer.Size = new UIntPtr(this.zstreamOutputSize);
this.outputBuffer.Position = UIntPtr.Zero;
// configure the inputBuffer
this.inputBuffer.Data = Marshal.UnsafeAddrOfPinnedArrayElement(buffer, offset);
this.inputBuffer.Size = new UIntPtr((uint)inputSize);
this.inputBuffer.Position = UIntPtr.Zero;
// compress inputBuffer to outputBuffer
Interop.ThrowIfError(Interop.ZSTD_compressStream(this.zstream, this.outputBuffer, this.inputBuffer));
// write data to output stream
var outputBufferPosition = (int)this.outputBuffer.Position.ToUInt32();
this.stream.Write(this.data, 0, outputBufferPosition);
// calculate progress in inputBuffer
var inputBufferPosition = (int)this.inputBuffer.Position.ToUInt32();
offset += inputBufferPosition;
count -= inputBufferPosition;
}
}
finally
{
alloc1.Free();
alloc2.Free();
}
}
public override long Seek(long offset, SeekOrigin origin)
{
if (origin != SeekOrigin.Current)
throw new NotImplementedException();
byte[] tmpBuff = new byte[1024];
long sizeToGo = offset;
while (sizeToGo > 0)
{
int sizenow = sizeToGo > 1024 ? 1024 : (int)sizeToGo;
Read(tmpBuff, 0, sizenow);
sizeToGo -= sizenow;
}
position += offset;
return offset;
}
public override void SetLength(long value)
{
throw new NotImplementedException();
}
//-----------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------
private void ProcessStream(Action<IntPtr, Interop.Buffer> outputAction)
{
var alloc = GCHandle.Alloc(this.data, GCHandleType.Pinned);
try
{
this.outputBuffer.Data = Marshal.UnsafeAddrOfPinnedArrayElement(this.data, 0);
this.outputBuffer.Size = new UIntPtr(this.zstreamOutputSize);
this.outputBuffer.Position = UIntPtr.Zero;
outputAction(this.zstream, this.outputBuffer);
var outputBufferPosition = (int)this.outputBuffer.Position.ToUInt32();
this.stream.Write(this.data, 0, outputBufferPosition);
}
finally
{
alloc.Free();
}
}
}
}

View File

@@ -1,204 +0,0 @@
using System;
using System.IO;
namespace Compress.SevenZip.Filters
{
public class BCJ2Filter : Stream
{
private Stream baseStream;
private long position = 0;
private byte[] output = new byte[4];
private int outputOffset = 0;
private int outputCount = 0;
private Stream control;
private Stream data1;
private Stream data2;
private ushort[] p = new ushort[256 + 2];
private uint range, code;
private byte prevByte = 0;
private const int kNumTopBits = 24;
private const int kTopValue = 1 << kNumTopBits;
private const int kNumBitModelTotalBits = 11;
private const int kBitModelTotal = 1 << kNumBitModelTotalBits;
private const int kNumMoveBits = 5;
private static bool IsJ(byte b0, byte b1)
{
return (b1 & 0xFE) == 0xE8 || IsJcc(b0, b1);
}
private static bool IsJcc(byte b0, byte b1)
{
return b0 == 0x0F && (b1 & 0xF0) == 0x80;
}
public BCJ2Filter(Stream baseStream, Stream data1, Stream data2, Stream control)
{
this.control = control;
this.data1 = data1;
this.data2 = data2;
this.baseStream = baseStream;
int i;
for (i = 0; i < p.Length; i++)
p[i] = kBitModelTotal >> 1;
code = 0;
range = 0xFFFFFFFF;
byte[] controlbuf = new byte[5];
control.Read(controlbuf, 0, 5);
for (i = 0; i < 5; i++)
code = (code << 8) | controlbuf[i];
}
public override bool CanRead
{
get { return true; }
}
public override bool CanSeek
{
get { return false; }
}
public override bool CanWrite
{
get { return false; }
}
public override void Flush()
{
throw new NotImplementedException();
}
public override long Length
{
get { return baseStream.Length + data1.Length + data2.Length; }
}
public override long Position
{
get
{
return position;
}
set
{
throw new NotImplementedException();
}
}
public override int Read(byte[] buffer, int offset, int count)
{
int size = 0;
byte b = 0;
while (size < count)
{
while (outputOffset < outputCount)
{
b = output[outputOffset++];
buffer[offset++] = b;
size++;
position++;
prevByte = b;
if (size == count)
return size;
}
b = (byte)baseStream.ReadByte();
buffer[offset++] = b;
size++;
position++;
if (!IsJ(prevByte, b))
prevByte = b;
else
{
int prob;
if (b == 0xE8)
prob = prevByte;
else if (b == 0xE9)
prob = 256;
else
prob = 257;
uint bound = (range >> kNumBitModelTotalBits) * p[prob];
if (code < bound)
{
range = bound;
p[prob] += (ushort)((kBitModelTotal - p[prob]) >> kNumMoveBits);
if (range < kTopValue)
{
range <<= 8;
code = (code << 8) | (byte)control.ReadByte();
}
prevByte = b;
}
else
{
range -= bound;
code -= bound;
p[prob] -= (ushort)(p[prob] >> kNumMoveBits);
if (range < kTopValue)
{
range <<= 8;
code = (code << 8) | (byte)control.ReadByte();
}
uint dest;
if (b == 0xE8)
dest = (uint)((data1.ReadByte() << 24) | (data1.ReadByte() << 16) | (data1.ReadByte() << 8) | data1.ReadByte());
else
dest = (uint)((data2.ReadByte() << 24) | (data2.ReadByte() << 16) | (data2.ReadByte() << 8) | data2.ReadByte());
dest -= (uint)(position + 4);
output[0] = (byte)dest;
output[1] = (byte)(dest >> 8);
output[2] = (byte)(dest >> 16);
output[3] = (byte)(dest >> 24);
outputOffset = 0;
outputCount = 4;
}
}
}
return size;
}
public override long Seek(long offset, SeekOrigin origin)
{
if (origin != SeekOrigin.Current)
throw new NotImplementedException();
const int bufferSize = 10240;
byte[] seekBuffer = new byte[bufferSize];
long seekToGo = offset;
while (seekToGo > 0)
{
long get = seekToGo > bufferSize ? bufferSize : seekToGo;
Read(seekBuffer, 0, (int)get);
seekToGo -= get;
}
return position;
}
public override void SetLength(long value)
{
throw new NotImplementedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotImplementedException();
}
}
}

View File

@@ -1,100 +0,0 @@
using System.IO;
namespace Compress.SevenZip.Filters
{
public class BCJFilter : Filter
{
private static readonly bool[] MASK_TO_ALLOWED_STATUS = new bool[] { true, true, true, false, true, false, false, false };
private static readonly int[] MASK_TO_BIT_NUMBER = new int[] { 0, 1, 2, 2, 3, 3, 3, 3 };
private int pos;
private int prevMask = 0;
public BCJFilter(bool isEncoder, Stream baseStream) : base(isEncoder, baseStream, 5)
{
pos = 5;
}
private static bool test86MSByte(byte b)
{
return b == 0x00 || b == 0xFF;
}
protected override int Transform(byte[] buffer, int offset, int count)
{
int prevPos = offset - 1;
int end = offset + count - 5;
int i;
for (i = offset; i <= end; ++i)
{
if ((buffer[i] & 0xFE) != 0xE8)
continue;
prevPos = i - prevPos;
if ((prevPos & ~3) != 0)
{ // (unsigned)prevPos > 3
prevMask = 0;
}
else
{
prevMask = (prevMask << (prevPos - 1)) & 7;
if (prevMask != 0)
{
if (!MASK_TO_ALLOWED_STATUS[prevMask] || test86MSByte(
buffer[i + 4 - MASK_TO_BIT_NUMBER[prevMask]]))
{
prevPos = i;
prevMask = (prevMask << 1) | 1;
continue;
}
}
}
prevPos = i;
if (test86MSByte(buffer[i + 4]))
{
int src = buffer[i + 1]
| (buffer[i + 2] << 8)
| (buffer[i + 3] << 16)
| (buffer[i + 4] << 24);
int dest;
while (true)
{
if (isEncoder)
dest = src + (pos + i - offset);
else
dest = src - (pos + i - offset);
if (prevMask == 0)
break;
int index = MASK_TO_BIT_NUMBER[prevMask] * 8;
if (!test86MSByte((byte)(dest >> (24 - index))))
break;
src = dest ^ ((1 << (32 - index)) - 1);
}
buffer[i + 1] = (byte)dest;
buffer[i + 2] = (byte)(dest >> 8);
buffer[i + 3] = (byte)(dest >> 16);
buffer[i + 4] = (byte)(~(((dest >> 24) & 1) - 1));
i += 4;
}
else
{
prevMask = (prevMask << 1) | 1;
}
}
prevPos = i - prevPos;
prevMask = ((prevPos & ~3) != 0) ? 0 : prevMask << (prevPos - 1);
i -= offset;
pos += i;
return i;
}
}
}

View File

@@ -1,100 +0,0 @@
using System;
using System.IO;
namespace Compress.SevenZip.Filters
{
public class Delta : Stream
{
private readonly Stream _baseStream;
private long _position;
private readonly byte[] _bVal;
private readonly int _dSize;
private int _bIndex;
// properties values are 0,1,3
public Delta(byte[] properties, Stream inputStream)
{
_dSize = properties[0] + 1;
_bVal = new byte[_dSize];
_baseStream = inputStream;
}
public override void Flush()
{
throw new NotImplementedException();
}
public override long Seek(long offset, SeekOrigin origin)
{
if (origin != SeekOrigin.Current)
throw new NotImplementedException();
const int bufferSize = 10240;
byte[] seekBuffer = new byte[bufferSize];
long seekToGo = offset;
while (seekToGo > 0)
{
long get = seekToGo > bufferSize ? bufferSize : seekToGo;
Read(seekBuffer, 0, (int)get);
seekToGo -= get;
}
return _position;
}
public override void SetLength(long value)
{
throw new NotImplementedException();
}
public override int Read(byte[] buffer, int offset, int count)
{
int read = _baseStream.Read(buffer, offset, count);
for (int i = 0; i < read; i++)
{
buffer[i] = _bVal[_bIndex] = (byte)(buffer[i] + _bVal[_bIndex]);
_bIndex = (_bIndex + 1) % _dSize;
}
_position += read;
return read;
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotImplementedException();
}
public override bool CanRead
{
get { return true; }
}
public override bool CanSeek
{
get { return false; }
}
public override bool CanWrite
{
get { return false; }
}
public override long Length
{
get { return _baseStream.Length; }
}
public override long Position
{
get
{
return _position;
}
set
{
throw new NotImplementedException();
}
}
}
}

View File

@@ -1,171 +0,0 @@
using System;
using System.IO;
namespace Compress.SevenZip.Filters
{
public abstract class Filter : Stream
{
protected bool isEncoder;
protected Stream baseStream;
private byte[] tail;
private byte[] window;
private int transformed = 0;
private int read = 0;
private bool endReached = false;
private long position = 0;
protected Filter(bool isEncoder, Stream baseStream, int lookahead)
{
this.isEncoder = isEncoder;
this.baseStream = baseStream;
tail = new byte[lookahead - 1];
window = new byte[tail.Length * 2];
}
public Stream BaseStream
{ get { return baseStream; } }
public override bool CanRead
{
get { return !isEncoder; }
}
public override bool CanSeek
{
get { return false; }
}
public override bool CanWrite
{
get { return isEncoder; }
}
public override void Flush()
{
throw new NotImplementedException();
}
public override long Length
{
get { return baseStream.Length; }
}
public override long Position
{
get
{
return position;
}
set
{
throw new NotImplementedException();
}
}
public override int Read(byte[] buffer, int offset, int count)
{
int size = 0;
if (transformed > 0)
{
int copySize = transformed;
if (copySize > count)
copySize = count;
Buffer.BlockCopy(tail, 0, buffer, offset, copySize);
transformed -= copySize;
read -= copySize;
offset += copySize;
count -= copySize;
size += copySize;
Buffer.BlockCopy(tail, copySize, tail, 0, read);
}
if (count == 0)
{
position += size;
return size;
}
int inSize = read;
if (inSize > count)
inSize = count;
Buffer.BlockCopy(tail, 0, buffer, offset, inSize);
read -= inSize;
Buffer.BlockCopy(tail, inSize, tail, 0, read);
while (!endReached && inSize < count)
{
int baseRead = baseStream.Read(buffer, offset + inSize, count - inSize);
inSize += baseRead;
if (baseRead == 0)
endReached = true;
}
while (!endReached && read < tail.Length)
{
int baseRead = baseStream.Read(tail, read, tail.Length - read);
read += baseRead;
if (baseRead == 0)
endReached = true;
}
if (inSize > tail.Length)
{
transformed = Transform(buffer, offset, inSize);
offset += transformed;
count -= transformed;
size += transformed;
inSize -= transformed;
transformed = 0;
}
if (count == 0)
{
position += size;
return size;
}
Buffer.BlockCopy(buffer, offset, window, 0, inSize);
Buffer.BlockCopy(tail, 0, window, inSize, read);
if (inSize + read > tail.Length)
transformed = Transform(window, 0, inSize + read);
else
transformed = inSize + read;
Buffer.BlockCopy(window, 0, buffer, offset, inSize);
Buffer.BlockCopy(window, inSize, tail, 0, read);
size += inSize;
transformed -= inSize;
position += size;
return size;
}
public override long Seek(long offset, SeekOrigin origin)
{
if (origin != SeekOrigin.Current)
throw new NotImplementedException();
const int bufferSize = 10240;
byte[] seekBuffer = new byte[bufferSize];
long seekToGo = offset;
while (seekToGo > 0)
{
long get = seekToGo > bufferSize ? bufferSize : seekToGo;
Read(seekBuffer, 0, (int)get);
seekToGo -= get;
}
return position;
}
public override void SetLength(long value)
{
throw new NotImplementedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
Transform(buffer, offset, count);
baseStream.Write(buffer, offset, count);
}
protected abstract int Transform(byte[] buffer, int offset, int count);
}
}

View File

@@ -1,177 +0,0 @@
using System.Collections.Generic;
using System.IO;
using System.Text;
using Compress.SevenZip.Structure;
using FileInfo = RVIO.FileInfo;
namespace Compress.SevenZip
{
public partial class SevenZ : ICompress
{
public static bool supportZstd
{
get;
private set;
}
public static void TestForZstd()
{
supportZstd = RVIO.File.Exists("libzstd.dll");
}
private class LocalFile
{
public string FileName;
public ulong UncompressedSize;
public bool IsDirectory;
public byte[] CRC;
public int StreamIndex;
public ulong StreamOffset;
public ZipReturn FileStatus = ZipReturn.ZipUntested;
}
private List<LocalFile> _localFiles = new List<LocalFile>();
private FileInfo _zipFileInfo;
private Stream _zipFs;
private SignatureHeader _signatureHeader;
private bool _compressed = true;
private long _baseOffset;
public string ZipFilename => _zipFileInfo != null ? _zipFileInfo.FullName : string.Empty;
public long TimeStamp => _zipFileInfo?.LastWriteTime ?? 0;
public ZipOpenType ZipOpen { get; private set; }
public ZipStatus ZipStatus { get; private set; }
public int LocalFilesCount()
{
return _localFiles.Count;
}
public string Filename(int i)
{
return _localFiles[i].FileName;
}
public ulong? LocalHeader(int i)
{
return 0;
}
public ulong UncompressedSize(int i)
{
return _localFiles[i].UncompressedSize;
}
public int StreamIndex(int i)
{
return _localFiles[i].StreamIndex;
}
public ZipReturn FileStatus(int i)
{
return _localFiles[i].FileStatus;
}
public byte[] CRC32(int i)
{
return _localFiles[i].CRC;
}
public void ZipFileCloseFailed()
{
switch (ZipOpen)
{
case ZipOpenType.Closed:
return;
case ZipOpenType.OpenRead:
ZipFileCloseReadStream();
if (_zipFs != null)
{
_zipFs.Close();
_zipFs.Dispose();
}
break;
case ZipOpenType.OpenWrite:
_zipFs.Flush();
_zipFs.Close();
_zipFs.Dispose();
if (_zipFileInfo != null)
RVIO.File.Delete(_zipFileInfo.FullName);
_zipFileInfo = null;
break;
}
ZipOpen = ZipOpenType.Closed;
}
public bool IsDirectory(int i)
{
return _localFiles[i].IsDirectory;
}
public void ZipFileClose()
{
switch (ZipOpen)
{
case ZipOpenType.Closed:
return;
case ZipOpenType.OpenRead:
ZipFileCloseReadStream();
if (_zipFs != null)
{
_zipFs.Close();
_zipFs.Dispose();
}
ZipOpen = ZipOpenType.Closed;
return;
case ZipOpenType.OpenWrite:
CloseWriting7Zip();
if (_zipFileInfo != null)
_zipFileInfo = new FileInfo(_zipFileInfo.FullName);
break;
}
ZipOpen = ZipOpenType.Closed;
}
private Header _header;
public StringBuilder HeaderReport()
{
StringBuilder sb = new StringBuilder();
if (_header == null)
{
sb.AppendLine("Null Header");
return sb;
}
_header.Report(ref sb);
return sb;
}
}
}

View File

@@ -1,170 +0,0 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using Compress.SevenZip.Structure;
using Compress.Utils;
using FileInfo = RVIO.FileInfo;
using FileStream = RVIO.FileStream;
namespace Compress.SevenZip
{
public partial class SevenZ
{
public ZipReturn ZipFileOpen(string filename, long timestamp, bool readHeaders)
{
ZipFileClose();
Debug.WriteLine(filename);
#region open file stream
try
{
if (!RVIO.File.Exists(filename))
{
ZipFileClose();
return ZipReturn.ZipErrorFileNotFound;
}
_zipFileInfo = new FileInfo(filename);
if ((timestamp != -1) && (_zipFileInfo.LastWriteTime != timestamp))
{
ZipFileClose();
return ZipReturn.ZipErrorTimeStamp;
}
int errorCode = FileStream.OpenFileRead(filename, out _zipFs);
if (errorCode != 0)
{
ZipFileClose();
return ZipReturn.ZipErrorOpeningFile;
}
}
catch (PathTooLongException)
{
ZipFileClose();
return ZipReturn.ZipFileNameToLong;
}
catch (IOException)
{
ZipFileClose();
return ZipReturn.ZipErrorOpeningFile;
}
#endregion
ZipOpen = ZipOpenType.OpenRead;
ZipStatus = ZipStatus.None;
return ZipFileReadHeaders();
}
public ZipReturn ZipFileOpen(Stream inStream)
{
ZipFileClose();
_zipFileInfo = null;
_zipFs = inStream;
ZipOpen = ZipOpenType.OpenRead;
ZipStatus = ZipStatus.None;
return ZipFileReadHeaders();
}
private ZipReturn ZipFileReadHeaders()
{
try
{
SignatureHeader signatureHeader = new SignatureHeader();
if (!signatureHeader.Read(_zipFs))
{
return ZipReturn.ZipSignatureError;
}
_baseOffset = _zipFs.Position;
_zipFs.Seek(_baseOffset + (long)signatureHeader.NextHeaderOffset, SeekOrigin.Begin);
byte[] mainHeader = new byte[signatureHeader.NextHeaderSize];
_zipFs.Read(mainHeader, 0, (int)signatureHeader.NextHeaderSize);
if (!CRC.VerifyDigest(signatureHeader.NextHeaderCRC, mainHeader, 0, (uint)signatureHeader.NextHeaderSize))
return ZipReturn.Zip64EndOfCentralDirError;
if (signatureHeader.NextHeaderSize != 0)
{
_zipFs.Seek(_baseOffset + (long)signatureHeader.NextHeaderOffset, SeekOrigin.Begin);
ZipReturn zr = Header.ReadHeaderOrPackedHeader(_zipFs, _baseOffset, out _header);
if (zr != ZipReturn.ZipGood)
{
return zr;
}
}
ZipStatus = ZipStatus.None;
ZipStatus |= IsRomVault7Z(_baseOffset, signatureHeader.NextHeaderOffset, signatureHeader.NextHeaderSize, signatureHeader.NextHeaderCRC) ? ZipStatus.TrrntZip : ZipStatus.None;
_zipFs.Seek(_baseOffset + (long)(signatureHeader.NextHeaderOffset + signatureHeader.NextHeaderSize), SeekOrigin.Begin);
ZipStatus |= Istorrent7Z() ? ZipStatus.Trrnt7Zip : ZipStatus.None;
PopulateLocalFiles(out _localFiles);
return ZipReturn.ZipGood;
}
catch
{
ZipFileClose();
return ZipReturn.ZipErrorReadingFile;
}
}
private void PopulateLocalFiles(out List<LocalFile> localFiles)
{
int emptyFileIndex = 0;
int folderIndex = 0;
int unpackedStreamsIndex = 0;
ulong streamOffset = 0;
localFiles = new List<LocalFile>();
if (_header == null)
return;
for (int i = 0; i < _header.FileInfo.Names.Length; i++)
{
LocalFile lf = new LocalFile { FileName = _header.FileInfo.Names[i] };
if ((_header.FileInfo.EmptyStreamFlags == null) || !_header.FileInfo.EmptyStreamFlags[i])
{
lf.StreamIndex = folderIndex;
lf.StreamOffset = streamOffset;
lf.UncompressedSize = _header.StreamsInfo.Folders[folderIndex].UnpackedStreamInfo[unpackedStreamsIndex].UnpackedSize;
lf.CRC = Util.uinttobytes(_header.StreamsInfo.Folders[folderIndex].UnpackedStreamInfo[unpackedStreamsIndex].Crc);
streamOffset += lf.UncompressedSize;
unpackedStreamsIndex++;
if (unpackedStreamsIndex >= _header.StreamsInfo.Folders[folderIndex].UnpackedStreamInfo.Length)
{
folderIndex++;
unpackedStreamsIndex = 0;
streamOffset = 0;
}
}
else
{
lf.UncompressedSize = 0;
lf.CRC = new byte[] { 0, 0, 0, 0 };
lf.IsDirectory = (_header.FileInfo.EmptyFileFlags == null) || !_header.FileInfo.EmptyFileFlags[emptyFileIndex++];
if (lf.IsDirectory)
{
if (lf.FileName.Substring(lf.FileName.Length - 1, 1) != "/")
{
lf.FileName += "/";
}
}
}
localFiles.Add(lf);
}
}
}
}

View File

@@ -1,260 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using Compress.SevenZip.Compress.BZip2;
using Compress.SevenZip.Compress.LZMA;
using Compress.SevenZip.Compress.PPmd;
using Compress.SevenZip.Filters;
using Compress.SevenZip.Structure;
using Zstandard.Net;
using FileStream = RVIO.FileStream;
namespace Compress.SevenZip
{
public partial class SevenZ
{
private int _streamIndex = -1;
private Stream _stream;
public ZipReturn ZipFileOpenReadStream(int index, out Stream stream, out ulong unCompressedSize)
{
Debug.WriteLine("Opening File " + _localFiles[index].FileName);
stream = null;
unCompressedSize = 0;
try
{
if (ZipOpen != ZipOpenType.OpenRead)
{
return ZipReturn.ZipErrorGettingDataStream;
}
if (IsDirectory(index))
{
return ZipReturn.ZipTryingToAccessADirectory;
}
unCompressedSize = _localFiles[index].UncompressedSize;
int thisStreamIndex = _localFiles[index].StreamIndex;
ulong streamOffset = _localFiles[index].StreamOffset;
if ((thisStreamIndex == _streamIndex) && (streamOffset >= (ulong)_stream.Position))
{
stream = _stream;
stream.Seek((long)_localFiles[index].StreamOffset - _stream.Position, SeekOrigin.Current);
return ZipReturn.ZipGood;
}
ZipFileCloseReadStream();
_streamIndex = thisStreamIndex;
Folder folder = _header.StreamsInfo.Folders[_streamIndex];
// first make the List of Decompressors streams
int codersNeeded = folder.Coders.Length;
List<InStreamSourceInfo> allInputStreams = new List<InStreamSourceInfo>();
for (int i = 0; i < codersNeeded; i++)
{
folder.Coders[i].DecoderStream = null;
allInputStreams.AddRange(folder.Coders[i].InputStreamsSourceInfo);
}
// now use the binding pairs to links the outputs to the inputs
int bindPairsCount = folder.BindPairs.Length;
for (int i = 0; i < bindPairsCount; i++)
{
allInputStreams[(int)folder.BindPairs[i].InIndex].InStreamSource = InStreamSource.CompStreamOutput;
allInputStreams[(int)folder.BindPairs[i].InIndex].InStreamIndex = folder.BindPairs[i].OutIndex;
folder.Coders[(int)folder.BindPairs[i].OutIndex].OutputUsedInternally = true;
}
// next use the stream indises to connect the remaining input streams from the sourcefile
int packedStreamsCount = folder.PackedStreamIndices.Length;
for (int i = 0; i < packedStreamsCount; i++)
{
ulong packedStreamIndex = (ulong)i + folder.PackedStreamIndexBase;
// create and open the source file stream if needed
if (_header.StreamsInfo.PackedStreams[packedStreamIndex].PackedStream == null)
{
_header.StreamsInfo.PackedStreams[packedStreamIndex].PackedStream = CloneStream(_zipFs);
}
_header.StreamsInfo.PackedStreams[packedStreamIndex].PackedStream.Seek(
_baseOffset + (long)_header.StreamsInfo.PackedStreams[packedStreamIndex].StreamPosition, SeekOrigin.Begin);
allInputStreams[(int)folder.PackedStreamIndices[i]].InStreamSource = InStreamSource.FileStream;
allInputStreams[(int)folder.PackedStreamIndices[i]].InStreamIndex = packedStreamIndex;
}
List<Stream> inputCoders = new List<Stream>();
bool allCodersComplete = false;
while (!allCodersComplete)
{
allCodersComplete = true;
for (int i = 0; i < codersNeeded; i++)
{
Coder coder = folder.Coders[i];
// check is decoder already processed
if (coder.DecoderStream != null)
{
continue;
}
inputCoders.Clear();
for (int j = 0; j < (int)coder.NumInStreams; j++)
{
if (coder.InputStreamsSourceInfo[j].InStreamSource == InStreamSource.FileStream)
{
inputCoders.Add(_header.StreamsInfo.PackedStreams[coder.InputStreamsSourceInfo[j].InStreamIndex].PackedStream);
}
else if (coder.InputStreamsSourceInfo[j].InStreamSource == InStreamSource.CompStreamOutput)
{
if (folder.Coders[coder.InputStreamsSourceInfo[j].InStreamIndex].DecoderStream == null)
{
break;
}
inputCoders.Add(folder.Coders[coder.InputStreamsSourceInfo[j].InStreamIndex].DecoderStream);
}
else
{
// unknown input type so error
return ZipReturn.ZipDecodeError;
}
}
if (inputCoders.Count == (int)coder.NumInStreams)
{
// all inputs streams are available to make the decoder stream
switch (coder.DecoderType)
{
case DecompressType.Stored:
coder.DecoderStream = inputCoders[0];
break;
case DecompressType.Delta:
coder.DecoderStream = new Delta(folder.Coders[i].Properties, inputCoders[0]);
break;
case DecompressType.LZMA:
coder.DecoderStream = new LzmaStream(folder.Coders[i].Properties, inputCoders[0]);
break;
case DecompressType.LZMA2:
coder.DecoderStream = new LzmaStream(folder.Coders[i].Properties, inputCoders[0]);
break;
case DecompressType.PPMd:
coder.DecoderStream = new PpmdStream(new PpmdProperties(folder.Coders[i].Properties), inputCoders[0], false);
break;
case DecompressType.BZip2:
coder.DecoderStream = new CBZip2InputStream(inputCoders[0], false);
break;
case DecompressType.BCJ:
coder.DecoderStream = new BCJFilter(false, inputCoders[0]);
break;
case DecompressType.BCJ2:
coder.DecoderStream = new BCJ2Filter(inputCoders[0], inputCoders[1], inputCoders[2], inputCoders[3]);
break;
case DecompressType.ZSTD:
coder.DecoderStream = new ZstandardStream(inputCoders[0], CompressionMode.Decompress, true);
break;
default:
return ZipReturn.ZipDecodeError;
}
}
// if skipped a coder need to loop round again
if (coder.DecoderStream == null)
{
allCodersComplete = false;
}
}
}
// find the final output stream and return it.
int outputStream = -1;
for (int i = 0; i < codersNeeded; i++)
{
Coder coder = folder.Coders[i];
if (!coder.OutputUsedInternally)
{
outputStream = i;
}
}
stream = folder.Coders[outputStream].DecoderStream;
stream.Seek((long)_localFiles[index].StreamOffset, SeekOrigin.Current);
_stream = stream;
return ZipReturn.ZipGood;
}
catch (Exception e)
{
return ZipReturn.ZipErrorGettingDataStream;
}
}
private Stream CloneStream(Stream s)
{
switch (s)
{
case System.IO.FileStream _:
int errorCode = FileStream.OpenFileRead(ZipFilename, out Stream streamOut);
return errorCode != 0 ? null : streamOut;
case MemoryStream memStream:
long pos = memStream.Position;
memStream.Position = 0;
byte[] newStream = new byte[memStream.Length];
memStream.Read(newStream, 0, (int)memStream.Length);
MemoryStream ret = new MemoryStream(newStream, false);
memStream.Position = pos;
return ret;
}
return null;
}
public ZipReturn ZipFileCloseReadStream()
{
if (_streamIndex != -1)
{
Folder folder = _header.StreamsInfo.Folders[_streamIndex];
foreach (Coder c in folder.Coders)
{
Stream ds = c?.DecoderStream;
if (ds == null)
{
continue;
}
ds.Close();
ds.Dispose();
c.DecoderStream = null;
}
}
_streamIndex = -1;
if (_header?.StreamsInfo != null)
{
foreach (PackedStreamInfo psi in _header.StreamsInfo.PackedStreams)
{
if (psi?.PackedStream == null)
{
continue;
}
psi.PackedStream.Close();
psi.PackedStream.Dispose();
psi.PackedStream = null;
}
}
return ZipReturn.ZipGood;
}
}
}

View File

@@ -1,157 +0,0 @@
using System.IO;
using System.Text;
namespace Compress.SevenZip
{
public partial class SevenZ
{
// not finalized yet, so do not use
private void WriteRomVault7Zip(BinaryWriter bw, ulong headerPos, ulong headerLength, uint headerCRC)
{
const string sig = "RomVault7Z01";
byte[] RV7Zid = Util.Enc.GetBytes(sig);
// RomVault 7Zip torrent header
// 12 bytes : RomVault7Zip
// 4 bytes : HeaderCRC
// 8 bytes : HeaderPos
// 8 bytes : HeaderLength
bw.Write(RV7Zid);
bw.Write(headerCRC);
bw.Write(headerPos);
bw.Write(headerLength);
ZipStatus = ZipStatus.TrrntZip;
}
private bool IsRomVault7Z(long testBaseOffset, ulong testHeaderPos, ulong testHeaderLength, uint testHeaderCRC)
{
long length = _zipFs.Length;
if (length < 32)
{
return false;
}
_zipFs.Seek(_baseOffset + (long)testHeaderPos - 32, SeekOrigin.Begin);
const string sig = "RomVault7Z01";
byte[] rv7Zid = Util.Enc.GetBytes(sig);
byte[] header = new byte[12];
_zipFs.Read(header, 0, 12);
for (int i = 0; i < 12; i++)
{
if (header[i] != rv7Zid[i])
{
return false;
}
}
uint headerCRC;
ulong headerOffset; // is location of header in file
ulong headerSize;
using (BinaryReader br = new BinaryReader(_zipFs, Encoding.UTF8, true))
{
headerCRC = br.ReadUInt32();
headerOffset = br.ReadUInt64();
headerSize = br.ReadUInt64();
}
if (headerCRC != testHeaderCRC)
return false;
if (headerOffset != testHeaderPos + (ulong)testBaseOffset)
return false;
return headerSize == testHeaderLength;
}
private bool Istorrent7Z()
{
const int crcsz = 128;
const int t7ZsigSize = 16 + 1 + 9 + 4 + 4;
byte[] kSignature = { (byte)'7', (byte)'z', 0xBC, 0xAF, 0x27, 0x1C };
int kSignatureSize = kSignature.Length;
const string sig = "\xa9\x9f\xd1\x57\x08\xa9\xd7\xea\x29\x64\xb2\x36\x1b\x83\x52\x33\x01torrent7z_0.9beta";
byte[] t7Zid = Util.Enc.GetBytes(sig);
int t7ZidSize = t7Zid.Length;
const int tmpbufsize = 256 + t7ZsigSize + 8 + 4;
byte[] buffer = new byte[tmpbufsize];
// read fist 128 bytes, pad with zeros if less bytes
int bufferPos = 0;
_zipFs.Seek(0, SeekOrigin.Begin);
int ar = _zipFs.Read(buffer, bufferPos, crcsz);
if (ar < crcsz)
{
Util.memset(buffer, bufferPos + ar, 0, crcsz - ar);
}
bufferPos = crcsz;
long foffs = _zipFs.Length;
int endReadLength = crcsz + t7ZsigSize + 4;
foffs = foffs < endReadLength ? 0 : foffs - endReadLength;
_zipFs.Seek(foffs, SeekOrigin.Begin);
ar = _zipFs.Read(buffer, bufferPos, endReadLength);
if (ar < endReadLength)
{
if (ar >= t7ZsigSize + 4)
{
ar -= t7ZsigSize + 4;
}
if (ar < kSignatureSize)
{
ar = kSignatureSize;
}
Util.memset(buffer, bufferPos + ar, 0, crcsz - ar);
Util.memcpyr(buffer, crcsz * 2 + 8, buffer, bufferPos + ar, t7ZsigSize + 4);
}
else
{
Util.memcpyr(buffer, crcsz * 2 + 8, buffer, crcsz * 2, t7ZsigSize + 4);
}
foffs = _zipFs.Length;
foffs -= t7ZsigSize + 4;
//memcpy(buffer, crcsz * 2, &foffs, 8);
buffer[crcsz * 2 + 0] = (byte)((foffs >> 0) & 0xff);
buffer[crcsz * 2 + 1] = (byte)((foffs >> 8) & 0xff);
buffer[crcsz * 2 + 2] = (byte)((foffs >> 16) & 0xff);
buffer[crcsz * 2 + 3] = (byte)((foffs >> 24) & 0xff);
buffer[crcsz * 2 + 4] = 0;
buffer[crcsz * 2 + 5] = 0;
buffer[crcsz * 2 + 6] = 0;
buffer[crcsz * 2 + 7] = 0;
if (Util.memcmp(buffer, 0, kSignature, kSignatureSize))
{
t7Zid[16] = buffer[crcsz * 2 + 4 + 8 + 16];
if (Util.memcmp(buffer, crcsz * 2 + 4 + 8, t7Zid, t7ZidSize))
{
uint inCrc32 = (uint)(buffer[crcsz * 2 + 8 + 0] +
(buffer[crcsz * 2 + 8 + 1] << 8) +
(buffer[crcsz * 2 + 8 + 2] << 16) +
(buffer[crcsz * 2 + 8 + 3] << 24));
buffer[crcsz * 2 + 8 + 0] = 0xff;
buffer[crcsz * 2 + 8 + 1] = 0xff;
buffer[crcsz * 2 + 8 + 2] = 0xff;
buffer[crcsz * 2 + 8 + 3] = 0xff;
uint calcCrc32 = Utils.CRC.CalculateDigest(buffer, 0, crcsz * 2 + 8 + t7ZsigSize + 4);
if (inCrc32 == calcCrc32)
{
return true;
}
}
}
return false;
}
}
}

View File

@@ -1,176 +0,0 @@
using System.IO;
using System.Text;
using Compress.SevenZip.Compress.LZMA;
using Compress.SevenZip.Structure;
using Compress.Utils;
using FileInfo = RVIO.FileInfo;
using FileStream = RVIO.FileStream;
namespace Compress.SevenZip
{
public partial class SevenZ
{
private Stream _lzmaStream;
private ulong _packStreamStart;
private ulong _packStreamSize;
private ulong _unpackedStreamSize;
private byte[] _codeMSbytes;
public ZipReturn ZipFileCreate(string newFilename)
{
return ZipFileCreate(newFilename, true);
}
public ZipReturn ZipFileCreateFromUncompressedSize(string newFilename, ulong unCompressedSize)
{
return ZipFileCreate(newFilename, true, GetDictionarySizeFromUncompressedSize(unCompressedSize));
}
public ZipReturn ZipFileCreate(string newFilename, bool compressOutput, int dictionarySize = 1 << 24, int numFastBytes = 64)
{
if (ZipOpen != ZipOpenType.Closed)
{
return ZipReturn.ZipFileAlreadyOpen;
}
DirUtil.CreateDirForFile(newFilename);
_zipFileInfo = new FileInfo(newFilename);
int errorCode = FileStream.OpenFileWrite(newFilename, out _zipFs);
if (errorCode != 0)
{
ZipFileClose();
return ZipReturn.ZipErrorOpeningFile;
}
ZipOpen = ZipOpenType.OpenWrite;
_signatureHeader = new SignatureHeader();
_header = new Header();
using (BinaryWriter bw = new BinaryWriter(_zipFs, Encoding.UTF8, true))
{
_signatureHeader.Write(bw);
}
_baseOffset = _zipFs.Position;
_compressed = compressOutput;
_unpackedStreamSize = 0;
if (_compressed)
{
LzmaEncoderProperties ep = new LzmaEncoderProperties(true, dictionarySize, numFastBytes);
LzmaStream lzs = new LzmaStream(ep, false, _zipFs);
_codeMSbytes = lzs.Properties;
_lzmaStream = lzs;
/*
ZstandardStream zss = new ZstandardStream(_zipFs, 22, true);
_codeMSbytes = new byte[] { 1, 4, 18, 0, 0 };
_lzmaStream = zss;
*/
_packStreamStart = (ulong)_zipFs.Position;
}
return ZipReturn.ZipGood;
}
public void ZipFileAddDirectory(string filename)
{
string fName = filename;
if (fName.Substring(fName.Length - 1, 1) == @"/")
fName = fName.Substring(0, fName.Length - 1);
LocalFile lf = new LocalFile
{
FileName = fName,
UncompressedSize = 0,
IsDirectory = true,
StreamOffset = 0
};
_localFiles.Add(lf);
}
public void ZipFileAddZeroLengthFile()
{
// do nothing here for 7zip
}
public ZipReturn ZipFileOpenWriteStream(bool raw, bool trrntzip, string filename, ulong uncompressedSize, ushort compressionMethod, uint? datetime, out Stream stream)
{
return ZipFileOpenWriteStream(filename, uncompressedSize, out stream);
}
private ZipReturn ZipFileOpenWriteStream(string filename, ulong uncompressedSize, out Stream stream)
{
LocalFile lf = new LocalFile
{
FileName = filename,
UncompressedSize = uncompressedSize,
StreamOffset = (ulong)(_zipFs.Position - _signatureHeader.BaseOffset)
};
if (uncompressedSize == 0 && filename.Substring(filename.Length - 1, 1) == "/")
{
lf.FileName = filename.Substring(0, filename.Length - 1);
lf.IsDirectory = true;
}
_unpackedStreamSize += uncompressedSize;
_localFiles.Add(lf);
stream = _compressed ? _lzmaStream : _zipFs;
return ZipReturn.ZipGood;
}
public ZipReturn ZipFileCloseWriteStream(byte[] crc32)
{
_localFiles[_localFiles.Count - 1].CRC = new[] { crc32[3], crc32[2], crc32[1], crc32[0] };
return ZipReturn.ZipGood;
}
private static readonly int[] DictionarySizes =
{
0x10000,
0x18000,
0x20000,
0x30000,
0x40000,
0x60000,
0x80000,
0xc0000,
0x100000,
0x180000,
0x200000,
0x300000,
0x400000,
0x600000,
0x800000,
0xc00000,
0x1000000,
0x1800000,
0x2000000,
0x3000000,
0x4000000,
0x6000000
};
private static int GetDictionarySizeFromUncompressedSize(ulong unCompressedSize)
{
foreach (int v in DictionarySizes)
{
if ((ulong)v >= unCompressedSize)
return v;
}
return DictionarySizes[DictionarySizes.Length - 1];
}
}
}

View File

@@ -1,293 +0,0 @@
using System.IO;
using System.Text;
using Compress.SevenZip.Compress.LZMA;
using Compress.SevenZip.Structure;
using Compress.Utils;
using Zstandard.Net;
namespace Compress.SevenZip
{
public partial class SevenZ
{
private void Create7ZStructure()
{
int fileCount = _localFiles.Count;
//FileInfo
_header.FileInfo = new Structure.FileInfo
{
Names = new string[fileCount]
};
ulong emptyStreamCount = 0;
ulong emptyFileCount = 0;
for (int i = 0; i < fileCount; i++)
{
_header.FileInfo.Names[i] = _localFiles[i].FileName;
if (_localFiles[i].UncompressedSize != 0)
{
continue;
}
if (!_localFiles[i].IsDirectory)
{
emptyFileCount += 1;
}
emptyStreamCount += 1;
}
ulong outFileCount = (ulong)_localFiles.Count - emptyStreamCount;
_header.FileInfo.EmptyStreamFlags = null;
_header.FileInfo.EmptyFileFlags = null;
_header.FileInfo.Attributes = null;
if (emptyStreamCount > 0)
{
if (emptyStreamCount != emptyFileCount) //then we found directories and need to set the attributes
{
_header.FileInfo.Attributes = new uint[fileCount];
}
if (emptyFileCount > 0)
{
_header.FileInfo.EmptyFileFlags = new bool[emptyStreamCount];
}
emptyStreamCount = 0;
_header.FileInfo.EmptyStreamFlags = new bool[fileCount];
for (int i = 0; i < fileCount; i++)
{
if (_localFiles[i].UncompressedSize != 0)
{
continue;
}
if (_localFiles[i].IsDirectory)
{
if (_header.FileInfo.Attributes != null)
_header.FileInfo.Attributes[i] = 0x10; // set attributes to directory
}
else
{
if (_header.FileInfo.EmptyFileFlags != null)
_header.FileInfo.EmptyFileFlags[emptyStreamCount] = true; // set empty file flag
}
_header.FileInfo.EmptyStreamFlags[i] = true;
emptyStreamCount += 1;
}
}
//StreamsInfo
_header.StreamsInfo = new StreamsInfo { PackPosition = 0 };
//StreamsInfo.PackedStreamsInfo
if (_compressed)
{
_header.StreamsInfo.PackedStreams = new PackedStreamInfo[1];
_header.StreamsInfo.PackedStreams[0] = new PackedStreamInfo { PackedSize = _packStreamSize };
}
else
{
_header.StreamsInfo.PackedStreams = new PackedStreamInfo[outFileCount];
int fileIndex = 0;
for (int i = 0; i < fileCount; i++)
{
if (_localFiles[i].UncompressedSize == 0)
{
continue;
}
_header.StreamsInfo.PackedStreams[fileIndex++] = new PackedStreamInfo { PackedSize = _localFiles[i].UncompressedSize };
}
}
//StreamsInfo.PackedStreamsInfo, no CRC or StreamPosition required
if (_compressed)
{
//StreamsInfo.Folders
_header.StreamsInfo.Folders = new Folder[1];
//StreamsInfo.Folders.Coder
// flags 0x23
Folder folder = new Folder
{
BindPairs = null,
Coders = new[] {
new Coder {
Method = new byte[] { 3, 1, 1 },
NumInStreams = 1,
NumOutStreams = 1,
Properties = _codeMSbytes
}
},
PackedStreamIndices = new[] { (ulong)0 },
UnpackedStreamSizes = new[] { _unpackedStreamSize },
UnpackedStreamInfo = new UnpackedStreamInfo[outFileCount],
UnpackCRC = null
};
switch (_lzmaStream)
{
case LzmaStream _:
folder.Coders[0].Method = new byte[] { 3, 1, 1 };
break;
case ZstandardStream _:
folder.Coders[0].Method = new byte[] { 4, 247, 17, 1 };
break;
}
int fileIndex = 0;
for (int i = 0; i < fileCount; i++)
{
if (_localFiles[i].UncompressedSize == 0)
{
continue;
}
UnpackedStreamInfo unpackedStreamInfo = new UnpackedStreamInfo
{
UnpackedSize = _localFiles[i].UncompressedSize,
Crc = Util.bytestouint(_localFiles[i].CRC)
};
folder.UnpackedStreamInfo[fileIndex++] = unpackedStreamInfo;
}
_header.StreamsInfo.Folders[0] = folder;
}
else
{
_header.StreamsInfo.Folders = new Folder[outFileCount];
int fileIndex = 0;
for (int i = 0; i < fileCount; i++)
{
if (_localFiles[i].UncompressedSize == 0)
{
continue;
}
Folder folder = new Folder
{
BindPairs = null,
Coders = new[] {
new Coder {
Method = new byte[] {0},
NumInStreams = 1,
NumOutStreams = 1,
Properties = null
}
},
PackedStreamIndices = new[] { (ulong)i },
UnpackedStreamSizes = new[] { _localFiles[i].UncompressedSize },
UnpackCRC = null,
UnpackedStreamInfo = new[] {
new UnpackedStreamInfo {
UnpackedSize = _localFiles[i].UncompressedSize,
Crc = Util.bytestouint(_localFiles[i].CRC)
}
}
};
_header.StreamsInfo.Folders[fileIndex++] = folder;
}
}
}
private void CloseWriting7Zip()
{
if (_compressed)
{
_lzmaStream.Close();
}
_packStreamSize = (ulong)_zipFs.Position - _packStreamStart;
Create7ZStructure();
byte[] newHeaderByte;
using (Stream headerMem = new MemoryStream())
{
using (BinaryWriter headerBw = new BinaryWriter(headerMem, Encoding.UTF8, true))
{
_header.WriteHeader(headerBw);
newHeaderByte = new byte[headerMem.Length];
headerMem.Position = 0;
headerMem.Read(newHeaderByte, 0, newHeaderByte.Length);
}
}
uint mainHeaderCRC = CRC.CalculateDigest(newHeaderByte, 0, (uint)newHeaderByte.Length);
#region Header Compression
long packedHeaderPos = _zipFs.Position;
LzmaEncoderProperties ep = new LzmaEncoderProperties(true, GetDictionarySizeFromUncompressedSize((ulong)newHeaderByte.Length), 64);
LzmaStream lzs = new LzmaStream(ep, false, _zipFs);
byte[] lzmaStreamProperties = lzs.Properties;
lzs.Write(newHeaderByte, 0, newHeaderByte.Length);
lzs.Close();
StreamsInfo streamsInfo = new StreamsInfo
{
PackPosition = (ulong)(packedHeaderPos - _baseOffset),
Folders = new[] {
new Folder {
BindPairs = new BindPair[0],
Coders = new [] {
new Coder {
Method = new byte[] { 3, 1, 1 },
NumInStreams = 1,
NumOutStreams = 1,
Properties = lzmaStreamProperties
}
},
UnpackedStreamSizes = new[] {(ulong) newHeaderByte.Length},
UnpackCRC = mainHeaderCRC
}
},
PackedStreams = new[] {
new PackedStreamInfo
{
PackedSize = (ulong)(_zipFs.Position - packedHeaderPos),
StreamPosition = 0
}
}
};
using (Stream headerMem = new MemoryStream())
{
using (BinaryWriter bw = new BinaryWriter(headerMem, Encoding.UTF8, true))
{
bw.Write((byte)HeaderProperty.kEncodedHeader);
streamsInfo.WriteHeader(bw);
newHeaderByte = new byte[headerMem.Length];
headerMem.Position = 0;
headerMem.Read(newHeaderByte, 0, newHeaderByte.Length);
}
}
mainHeaderCRC = CRC.CalculateDigest(newHeaderByte, 0, (uint)newHeaderByte.Length);
#endregion
using (BinaryWriter bw = new BinaryWriter(_zipFs, Encoding.UTF8, true))
{
ulong headerPosition = (ulong)_zipFs.Position + 32; //tzip header is 32 bytes
WriteRomVault7Zip(bw, headerPosition, (ulong)newHeaderByte.Length, mainHeaderCRC);
_zipFs.Write(newHeaderByte, 0, newHeaderByte.Length);
_signatureHeader.WriteFinal(bw, headerPosition, (ulong)newHeaderByte.Length, mainHeaderCRC);
}
_zipFs.Flush();
_zipFs.Close();
_zipFs.Dispose();
}
}
}

View File

@@ -1,30 +0,0 @@
using System.IO;
using System.Text;
namespace Compress.SevenZip.Structure
{
public class BindPair
{
public ulong InIndex;
public ulong OutIndex;
public void Read(BinaryReader br)
{
InIndex = br.ReadEncodedUInt64();
OutIndex = br.ReadEncodedUInt64();
}
public void Write(BinaryWriter bw)
{
bw.WriteEncodedUInt64(InIndex);
bw.WriteEncodedUInt64(OutIndex);
}
public void Report(ref StringBuilder sb)
{
sb.AppendLine(" InIndex = " + InIndex);
sb.AppendLine(" OutIndex = " + OutIndex);
}
}
}

View File

@@ -1,162 +0,0 @@
using System;
using System.IO;
using System.Text;
using Compress.Utils;
namespace Compress.SevenZip.Structure
{
public enum InStreamSource
{
Unknown,
FileStream,
CompStreamOutput
}
public class InStreamSourceInfo
{
public InStreamSource InStreamSource = InStreamSource.Unknown;
public ulong InStreamIndex;
}
public enum DecompressType
{
Unknown,
Stored,
Delta,
LZMA,
BCJ,
BCJ2,
PPMd,
BZip2,
LZMA2,
ZSTD
}
public class Coder
{
public byte[] Method;
public ulong NumInStreams;
public ulong NumOutStreams;
public byte[] Properties;
/************Local Variables***********/
public DecompressType DecoderType;
public bool OutputUsedInternally = false;
public InStreamSourceInfo[] InputStreamsSourceInfo;
public Stream DecoderStream;
public void Read(BinaryReader br)
{
byte flags = br.ReadByte();
int decompressionMethodIdSize = flags & 0xf;
Method = br.ReadBytes(decompressionMethodIdSize);
if ((flags & 0x10) != 0)
{
NumInStreams = br.ReadEncodedUInt64();
NumOutStreams = br.ReadEncodedUInt64();
}
else
{
NumInStreams = 1;
NumOutStreams = 1;
}
if ((flags & 0x20) != 0)
{
ulong propSize = br.ReadEncodedUInt64();
Properties = br.ReadBytes((int)propSize);
}
if ((flags & 0x80) != 0)
{
throw new NotSupportedException("External flag");
}
if (Method.Length == 1 && Method[0] == 0)
{
DecoderType = DecompressType.Stored;
}
else if (Method.Length == 1 && Method[0] == 3)
{
DecoderType = DecompressType.Delta;
}
else if (Method.Length == 3 && Method[0] == 3 && Method[1] == 1 && Method[2] == 1)
{
DecoderType = DecompressType.LZMA;
}
else if (Method.Length == 4 && Method[0] == 3 && Method[1] == 3 && Method[2] == 1 && Method[3] == 3)
{
DecoderType = DecompressType.BCJ;
}
else if (Method.Length == 4 && Method[0] == 3 && Method[1] == 3 && Method[2] == 1 && Method[3] == 27)
{
DecoderType = DecompressType.BCJ2;
}
else if (Method.Length == 3 && Method[0] == 3 && Method[1] == 4 && Method[2] == 1)
{
DecoderType = DecompressType.PPMd;
}
else if (Method.Length == 3 && Method[0] == 4 && Method[1] == 2 && Method[2] == 2)
{
DecoderType = DecompressType.BZip2;
}
else if (Method.Length == 1 && Method[0] == 33)
{
DecoderType = DecompressType.LZMA2;
}
else if (SevenZ.supportZstd && Method.Length == 4 && Method[0] == 4 && Method[1] == 247 && Method[2] == 17 && Method[3] == 1)
{
DecoderType = DecompressType.ZSTD;
}
InputStreamsSourceInfo = new InStreamSourceInfo[NumInStreams];
for (uint i = 0; i < NumInStreams; i++)
{
InputStreamsSourceInfo[i] = new InStreamSourceInfo();
}
}
public void Write(BinaryWriter bw)
{
byte flags = (byte)Method.Length;
if ((NumInStreams != 1) || (NumOutStreams != 1))
{
flags = (byte)(flags | 0x10);
}
if ((Properties != null) && (Properties.Length > 0))
{
flags = (byte)(flags | 0x20);
}
bw.Write(flags);
bw.Write(Method);
if ((NumInStreams != 1) || (NumOutStreams != 1))
{
bw.WriteEncodedUInt64(NumInStreams);
bw.WriteEncodedUInt64(NumOutStreams);
}
if ((Properties != null) && (Properties.Length > 0))
{
bw.WriteEncodedUInt64((ulong)Properties.Length);
bw.Write(Properties);
}
}
public void Report(ref StringBuilder sb)
{
sb.AppendLine($" Method[] = {Method.ToArrayString()} : {DecoderType}");
sb.AppendLine($" NumInStreams = {NumInStreams}");
sb.AppendLine($" NumOutStreams = {NumOutStreams}");
sb.AppendLine($" Properties[] = {Properties.ToArrayString()}");
}
}
}

View File

@@ -1,140 +0,0 @@
using System;
using System.IO;
using System.Text;
namespace Compress.SevenZip.Structure
{
public class FileInfo
{
public string[] Names;
public bool[] EmptyStreamFlags;
public bool[] EmptyFileFlags;
public uint[] Attributes;
public void Read(BinaryReader br)
{
ulong size = br.ReadEncodedUInt64();
Names = new string[size];
ulong numEmptyFiles = 0;
for (; ; )
{
HeaderProperty hp = (HeaderProperty)br.ReadByte();
if (hp == HeaderProperty.kEnd)
{
return;
}
ulong bytessize = br.ReadEncodedUInt64();
switch (hp)
{
case HeaderProperty.kName:
if (br.ReadByte() != 0)
{
throw new Exception("Cannot be external");
}
for (ulong i = 0; i < size; i++)
{
Names[i] = br.ReadName();
}
continue;
case HeaderProperty.kEmptyStream:
EmptyStreamFlags = Util.ReadBoolFlags(br, (ulong)Names.Length);
for (ulong i = 0; i < size; i++)
{
if (EmptyStreamFlags[i])
{
numEmptyFiles++;
}
}
continue;
case HeaderProperty.kEmptyFile:
EmptyFileFlags = Util.ReadBoolFlags(br, numEmptyFiles);
continue;
case HeaderProperty.kWinAttributes:
Attributes = Util.ReadUInt32Def(br, size);
continue;
// don't know what this is.
case HeaderProperty.kAnti:
br.ReadBytes((int)bytessize);
continue;
case HeaderProperty.kCreationTime:
case HeaderProperty.kLastAccessTime:
case HeaderProperty.kLastWriteTime:
br.ReadBytes((int)bytessize);
continue;
case HeaderProperty.kDummy:
br.ReadBytes((int)bytessize);
continue;
default:
throw new Exception(hp.ToString());
}
}
}
public void Write(BinaryWriter bw)
{
bw.Write((byte)HeaderProperty.kFilesInfo);
bw.WriteEncodedUInt64((ulong)Names.Length);
byte[] namebyte;
using (MemoryStream nameMem = new MemoryStream())
{
using (BinaryWriter nameBw = new BinaryWriter(nameMem, Encoding.UTF8, true))
{
nameBw.Write((byte)0); //not external
foreach (string name in Names)
{
nameBw.WriteName(name);
}
namebyte = new byte[nameMem.Length];
nameMem.Position = 0;
nameMem.Read(namebyte, 0, namebyte.Length);
}
}
bw.Write((byte)HeaderProperty.kName);
bw.WriteEncodedUInt64((ulong)namebyte.Length);
bw.Write(namebyte);
if (EmptyStreamFlags != null)
{
bw.Write((byte)HeaderProperty.kEmptyStream);
Util.WriteBoolFlags(bw, EmptyStreamFlags);
}
if (EmptyFileFlags != null)
{
bw.Write((byte)HeaderProperty.kEmptyFile);
Util.WriteBoolFlags(bw, EmptyFileFlags);
}
if (Attributes != null)
{
bw.Write((byte)HeaderProperty.kWinAttributes);
Util.WriteUint32Def(bw, Attributes);
}
bw.Write((byte)HeaderProperty.kEnd);
}
public void Report(ref StringBuilder sb)
{
sb.AppendLine(" FileInfo");
sb.AppendLine(" ------");
}
}
}

View File

@@ -1,442 +0,0 @@
using System;
using System.IO;
using System.Text;
using Compress.Utils;
namespace Compress.SevenZip.Structure
{
public class Folder
{
public Coder[] Coders;
public BindPair[] BindPairs;
public ulong PackedStreamIndexBase;
public ulong[] PackedStreamIndices;
public ulong[] UnpackedStreamSizes;
public uint? UnpackCRC;
public UnpackedStreamInfo[] UnpackedStreamInfo;
private void ReadFolder(BinaryReader br)
{
ulong numCoders = br.ReadEncodedUInt64();
Coders = new Coder[numCoders];
int numInStreams = 0;
int numOutStreams = 0;
for (ulong i = 0; i < numCoders; i++)
{
Coders[i] = new Coder();
Coders[i].Read(br);
numInStreams += (int)Coders[i].NumInStreams;
numOutStreams += (int)Coders[i].NumOutStreams;
}
int numBindPairs = numOutStreams - 1;
BindPairs = new BindPair[numBindPairs];
for (int i = 0; i < numBindPairs; i++)
{
BindPairs[i] = new BindPair();
BindPairs[i].Read(br);
}
if (numInStreams < numBindPairs)
{
throw new NotSupportedException("Error");
}
int numPackedStreams = numInStreams - numBindPairs;
PackedStreamIndices = new ulong[numPackedStreams];
if (numPackedStreams == 1)
{
uint pi = 0;
for (uint j = 0; j < numInStreams; j++)
{
for (uint k = 0; k < BindPairs.Length; k++)
{
if (BindPairs[k].InIndex == j)
{
continue;
}
PackedStreamIndices[pi++] = j;
break;
}
}
}
else
{
for (uint i = 0; i < numPackedStreams; i++)
{
PackedStreamIndices[i] = br.ReadEncodedUInt64();
}
}
}
private void ReadUnpackedStreamSize(BinaryReader br)
{
ulong outStreams = 0;
foreach (Coder c in Coders)
{
outStreams += c.NumOutStreams;
}
UnpackedStreamSizes = new ulong[outStreams];
for (uint j = 0; j < outStreams; j++)
{
UnpackedStreamSizes[j] = br.ReadEncodedUInt64();
}
}
private ulong GetUnpackSize()
{
ulong outStreams = 0;
foreach (Coder coder in Coders)
{
outStreams += coder.NumInStreams;
}
for (ulong j = 0; j < outStreams; j++)
{
bool found = false;
foreach (BindPair bindPair in BindPairs)
{
if (bindPair.OutIndex != j)
{
continue;
}
found = true;
break;
}
if (!found)
{
return UnpackedStreamSizes[j];
}
}
return 0;
}
public static void ReadUnPackInfo(BinaryReader br, out Folder[] Folders)
{
Folders = null;
for (; ; )
{
HeaderProperty hp = (HeaderProperty)br.ReadByte();
switch (hp)
{
case HeaderProperty.kFolder:
{
ulong numFolders = br.ReadEncodedUInt64();
Folders = new Folder[numFolders];
byte external = br.ReadByte();
switch (external)
{
case 0:
{
ulong folderIndex = 0;
for (uint i = 0; i < numFolders; i++)
{
Folders[i] = new Folder();
Folders[i].ReadFolder(br);
Folders[i].PackedStreamIndexBase = folderIndex;
folderIndex += (ulong)Folders[i].PackedStreamIndices.Length;
}
break;
}
case 1:
throw new NotSupportedException("External flag");
}
continue;
}
case HeaderProperty.kCodersUnPackSize:
{
for (uint i = 0; i < Folders.Length; i++)
{
Folders[i].ReadUnpackedStreamSize(br);
}
continue;
}
case HeaderProperty.kCRC:
{
uint?[] crcs;
Util.UnPackCRCs(br, (ulong)Folders.Length, out crcs);
for (int i = 0; i < Folders.Length; i++)
{
Folders[i].UnpackCRC = crcs[i];
}
continue;
}
case HeaderProperty.kEnd:
return;
default:
throw new Exception(hp.ToString());
}
}
}
public static void ReadSubStreamsInfo(BinaryReader br, ref Folder[] Folders)
{
for (; ; )
{
HeaderProperty hp = (HeaderProperty)br.ReadByte();
switch (hp)
{
case HeaderProperty.kNumUnPackStream:
{
for (int f = 0; f < Folders.Length; f++)
{
int numStreams = (int)br.ReadEncodedUInt64();
Folders[f].UnpackedStreamInfo = new UnpackedStreamInfo[numStreams];
for (int i = 0; i < numStreams; i++)
{
Folders[f].UnpackedStreamInfo[i] = new UnpackedStreamInfo();
}
}
continue;
}
case HeaderProperty.kSize:
{
for (int f = 0; f < Folders.Length; f++)
{
Folder folder = Folders[f];
if (folder.UnpackedStreamInfo.Length == 0)
{
continue;
}
ulong sum = 0;
for (int i = 0; i < folder.UnpackedStreamInfo.Length - 1; i++)
{
ulong size = br.ReadEncodedUInt64();
folder.UnpackedStreamInfo[i].UnpackedSize = size;
sum += size;
}
folder.UnpackedStreamInfo[folder.UnpackedStreamInfo.Length - 1].UnpackedSize =
folder.GetUnpackSize() - sum;
}
continue;
}
case HeaderProperty.kCRC:
{
ulong numCRC = 0;
foreach (Folder folder in Folders)
{
if (folder.UnpackedStreamInfo == null)
{
folder.UnpackedStreamInfo = new UnpackedStreamInfo[1];
folder.UnpackedStreamInfo[0] = new UnpackedStreamInfo();
folder.UnpackedStreamInfo[0].UnpackedSize = folder.GetUnpackSize();
}
if ((folder.UnpackedStreamInfo.Length != 1) || !folder.UnpackCRC.HasValue)
{
numCRC += (ulong)folder.UnpackedStreamInfo.Length;
}
}
int crcIndex = 0;
uint?[] crc;
Util.UnPackCRCs(br, numCRC, out crc);
for (uint i = 0; i < Folders.Length; i++)
{
Folder folder = Folders[i];
if ((folder.UnpackedStreamInfo.Length == 1) && folder.UnpackCRC.HasValue)
{
folder.UnpackedStreamInfo[0].Crc = folder.UnpackCRC;
}
else
{
for (uint j = 0; j < folder.UnpackedStreamInfo.Length; j++, crcIndex++)
{
folder.UnpackedStreamInfo[j].Crc = crc[crcIndex];
}
}
}
continue;
}
case HeaderProperty.kEnd:
return;
default:
throw new Exception(hp.ToString());
}
}
}
private void WriteFolder(BinaryWriter bw)
{
ulong numCoders = (ulong)Coders.Length;
bw.WriteEncodedUInt64(numCoders);
for (ulong i = 0; i < numCoders; i++)
{
Coders[i].Write(bw);
}
ulong numBindingPairs = BindPairs == null ? 0 : (ulong)BindPairs.Length;
for (ulong i = 0; i < numBindingPairs; i++)
{
BindPairs[i].Write(bw);
}
//need to look at PAckedStreamIndices but don't need them for basic writing I am doing
}
private void WriteUnpackedStreamSize(BinaryWriter bw)
{
ulong numUnpackedStreamSizes = (ulong)UnpackedStreamSizes.Length;
for (ulong i = 0; i < numUnpackedStreamSizes; i++)
{
bw.WriteEncodedUInt64(UnpackedStreamSizes[i]);
}
}
public static void WriteUnPackInfo(BinaryWriter bw, Folder[] Folders)
{
bw.Write((byte)HeaderProperty.kUnPackInfo);
bw.Write((byte)HeaderProperty.kFolder);
ulong numFolders = (ulong)Folders.Length;
bw.WriteEncodedUInt64(numFolders);
bw.Write((byte)0); //External Flag
for (ulong i = 0; i < numFolders; i++)
{
Folders[i].WriteFolder(bw);
}
bw.Write((byte)HeaderProperty.kCodersUnPackSize);
for (ulong i = 0; i < numFolders; i++)
{
Folders[i].WriteUnpackedStreamSize(bw);
}
bool hasCRC = false;
uint?[] CRCs = new uint?[numFolders];
for (ulong i = 0; i < numFolders; i++)
{
CRCs[i] = Folders[i].UnpackCRC;
hasCRC |= (CRCs[i] != null);
}
if (hasCRC)
{
bw.Write((byte)HeaderProperty.kCRC);
Util.WritePackedCRCs(bw, CRCs);
}
bw.Write((byte)HeaderProperty.kEnd);
}
public static void WriteSubStreamsInfo(BinaryWriter bw, Folder[] Folders)
{
bw.Write((byte)HeaderProperty.kSubStreamsInfo);
bw.Write((byte)HeaderProperty.kNumUnPackStream);
for (int f = 0; f < Folders.Length; f++)
{
ulong numStreams = (ulong)Folders[f].UnpackedStreamInfo.Length;
bw.WriteEncodedUInt64(numStreams);
}
bw.Write((byte)HeaderProperty.kSize);
for (int f = 0; f < Folders.Length; f++)
{
Folder folder = Folders[f];
for (int i = 0; i < folder.UnpackedStreamInfo.Length - 1; i++)
{
bw.WriteEncodedUInt64(folder.UnpackedStreamInfo[i].UnpackedSize);
}
}
bw.Write((byte)HeaderProperty.kCRC);
bw.Write((byte)1); // crc flags default to true
for (int f = 0; f < Folders.Length; f++)
{
Folder folder = Folders[f];
for (int i = 0; i < folder.UnpackedStreamInfo.Length; i++)
{
bw.Write(Util.uinttobytes(folder.UnpackedStreamInfo[i].Crc));
}
}
bw.Write((byte)HeaderProperty.kEnd);
}
public void Report(ref StringBuilder sb)
{
if (Coders == null)
{
sb.AppendLine(" Coders[] = null");
}
else
{
sb.AppendLine($" Coders[] = ({Coders.Length})");
foreach (Coder c in Coders)
{
c.Report(ref sb);
}
}
if (BindPairs == null)
{
sb.AppendLine(" BindPairs[] = null");
}
else
{
sb.AppendLine($" BindPairs[] = ({BindPairs.Length})");
foreach (BindPair bp in BindPairs)
{
bp.Report(ref sb);
}
}
sb.AppendLine($" PackedStreamIndexBase = {PackedStreamIndexBase}");
sb.AppendLine($" PackedStreamIndices[] = {PackedStreamIndices.ToArrayString()}");
sb.AppendLine($" UnpackedStreamSizes[] = {UnpackedStreamSizes.ToArrayString()}");
sb.AppendLine($" UnpackCRC = {UnpackCRC.ToHex()}");
if (UnpackedStreamInfo == null)
{
sb.AppendLine(" UnpackedStreamInfo[] = null");
}
else
{
sb.AppendLine($" UnpackedStreamInfo[{UnpackedStreamInfo.Length}]");
foreach (UnpackedStreamInfo usi in UnpackedStreamInfo)
{
usi.Report(ref sb);
}
}
}
}
}

View File

@@ -1,128 +0,0 @@
using System;
using System.IO;
using System.Text;
using Compress.SevenZip.Compress.LZMA;
using Compress.Utils;
namespace Compress.SevenZip.Structure
{
public class Header
{
public StreamsInfo StreamsInfo;
public FileInfo FileInfo;
public void Read(BinaryReader br)
{
for (; ; )
{
HeaderProperty hp = (HeaderProperty)br.ReadByte();
switch (hp)
{
case HeaderProperty.kMainStreamsInfo:
StreamsInfo = new StreamsInfo();
StreamsInfo.Read(br);
break;
case HeaderProperty.kFilesInfo:
FileInfo = new FileInfo();
FileInfo.Read(br);
break;
case HeaderProperty.kEnd:
return;
default:
throw new Exception(hp.ToString());
}
}
}
public void WriteHeader(BinaryWriter bw)
{
bw.Write((byte)HeaderProperty.kHeader);
StreamsInfo.Write(bw);
FileInfo.Write(bw);
bw.Write((byte)HeaderProperty.kEnd);
}
public static ZipReturn ReadHeaderOrPackedHeader(Stream stream, long baseOffset, out Header header)
{
header = null;
using (BinaryReader br = new BinaryReader(stream, Encoding.UTF8, true))
{
HeaderProperty hp = (HeaderProperty)br.ReadByte();
switch (hp)
{
case HeaderProperty.kEncodedHeader:
{
StreamsInfo streamsInfo = new StreamsInfo();
streamsInfo.Read(br);
if (streamsInfo.Folders.Length > 1)
{
return ZipReturn.ZipUnsupportedCompression;
}
Folder firstFolder = streamsInfo.Folders[0];
if (firstFolder.Coders.Length > 1)
{
return ZipReturn.ZipUnsupportedCompression;
}
byte[] method = firstFolder.Coders[0].Method;
if (!((method.Length == 3) && (method[0] == 3) && (method[1] == 1) && (method[2] == 1))) // LZMA
{
return ZipReturn.ZipUnsupportedCompression;
}
stream.Seek(baseOffset + (long)streamsInfo.PackPosition, SeekOrigin.Begin);
using (LzmaStream decoder = new LzmaStream(firstFolder.Coders[0].Properties, stream))
{
ZipReturn zr = ReadHeaderOrPackedHeader(decoder, baseOffset, out header);
if (zr != ZipReturn.ZipGood)
{
return zr;
}
}
return ZipReturn.ZipGood;
}
case HeaderProperty.kHeader:
{
header = new Header();
header.Read(br);
return ZipReturn.ZipGood;
}
}
return ZipReturn.ZipCentralDirError;
}
}
public void Report(ref StringBuilder sb)
{
sb.AppendLine("Header");
sb.AppendLine("------");
if (StreamsInfo == null)
{
sb.AppendLine("StreamsInfo == null");
}
else
{
StreamsInfo.Report(ref sb);
}
if (FileInfo == null)
{
sb.AppendLine("FileInfo == null");
}
else
{
FileInfo.Report(ref sb);
}
}
}
}

View File

@@ -1,98 +0,0 @@
using System;
using System.IO;
using System.Text;
using Compress.Utils;
namespace Compress.SevenZip.Structure
{
public class PackedStreamInfo
{
public ulong PackedSize;
public ulong? Crc;
public ulong StreamPosition;
public Stream PackedStream;
public static void Read(BinaryReader br, out ulong packPosition, out PackedStreamInfo[] packedStreams)
{
packPosition = br.ReadEncodedUInt64();
ulong numPackStreams = br.ReadEncodedUInt64();
packedStreams = new PackedStreamInfo[numPackStreams];
for (ulong i = 0; i < numPackStreams; i++)
{
packedStreams[i] = new PackedStreamInfo();
}
ulong streamPosition = 0;
for (; ; )
{
HeaderProperty hp = (HeaderProperty)br.ReadByte();
switch (hp)
{
case HeaderProperty.kSize:
for (ulong i = 0; i < numPackStreams; i++)
{
packedStreams[i].StreamPosition = streamPosition;
packedStreams[i].PackedSize = br.ReadEncodedUInt64();
streamPosition += packedStreams[i].PackedSize;
}
continue;
case HeaderProperty.kCRC:
for (ulong i = 0; i < numPackStreams; i++)
{
packedStreams[i].Crc = br.ReadEncodedUInt64();
}
continue;
case HeaderProperty.kEnd:
return;
default:
throw new Exception(hp.ToString());
}
}
}
public static void Write(BinaryWriter bw, ulong packPosition, PackedStreamInfo[] packedStreams)
{
ulong numPackStreams = (ulong)packedStreams.Length;
bw.Write((byte)HeaderProperty.kPackInfo);
bw.WriteEncodedUInt64(packPosition);
bw.WriteEncodedUInt64(numPackStreams);
bw.Write((byte)HeaderProperty.kSize);
ulong streamPosition = 0;
for (ulong i = 0; i < numPackStreams; i++)
{
packedStreams[i].StreamPosition = streamPosition;
bw.WriteEncodedUInt64(packedStreams[i].PackedSize);
streamPosition += packedStreams[i].PackedSize;
}
// Only checking the first CRC assuming all the reset will be the same
if (packedStreams[0].Crc != null)
{
bw.Write((byte)HeaderProperty.kCRC);
for (ulong i = 0; i < numPackStreams; i++)
{
bw.WriteEncodedUInt64(packedStreams[i].Crc ?? 0);
}
}
bw.Write((byte)HeaderProperty.kEnd);
}
public void Report(ref StringBuilder sb)
{
sb.AppendLine($" PackedSize = {PackedSize}");
sb.AppendLine($" Crc = {Crc.ToHex()}");
sb.AppendLine($" StreamPosition = {StreamPosition}");
}
}
}

View File

@@ -1,110 +0,0 @@
using System.IO;
using System.Text;
namespace Compress.SevenZip.Structure
{
internal class SignatureHeader
{
private static readonly byte[] Signature = { (byte)'7', (byte)'z', 0xBC, 0xAF, 0x27, 0x1C };
private byte _major;
private byte _minor;
private uint _startHeaderCRC;
public ulong NextHeaderOffset;
public ulong NextHeaderSize;
public uint NextHeaderCRC;
private long _crcOffset;
public long BaseOffset { get; private set; }
public bool Read(Stream stream)
{
using (BinaryReader br = new BinaryReader(stream, Encoding.UTF8, true))
{
byte[] signatureBytes = br.ReadBytes(6);
if (!signatureBytes.Compare(Signature))
{
return false;
}
_major = br.ReadByte();
_minor = br.ReadByte();
_startHeaderCRC = br.ReadUInt32();
long pos = br.BaseStream.Position;
byte[] mainHeader = new byte[8 + 8 + 4];
br.BaseStream.Read(mainHeader, 0, mainHeader.Length);
if (!Utils.CRC.VerifyDigest(_startHeaderCRC, mainHeader, 0, (uint)mainHeader.Length))
{
return false;
}
br.BaseStream.Seek(pos, SeekOrigin.Begin);
NextHeaderOffset = br.ReadUInt64();
NextHeaderSize = br.ReadUInt64();
NextHeaderCRC = br.ReadUInt32();
return true;
}
}
public void Write(BinaryWriter bw)
{
//SignatureHeader
//~~~~~~~~~~~~~~~
bw.Write(Signature);
//ArchiveVersion
//{
bw.Write((byte)0); // BYTE Major
bw.Write((byte)3); // BYTE Minor
//};
_crcOffset = bw.BaseStream.Position;
bw.Write((uint)0); //HeaderCRC
//StartHeader
//{
bw.Write((ulong)0); //NextHeaderOffset
bw.Write((ulong)0); //NextHeaderSize
bw.Write((uint)0); //NextHeaderCRC
//}
BaseOffset = bw.BaseStream.Position;
}
public void WriteFinal(BinaryWriter bw, ulong headerpos, ulong headerLength, uint headerCRC)
{
long fileEnd = bw.BaseStream.Position;
byte[] sigHeaderBytes;
using (MemoryStream sigHeaderMem = new MemoryStream())
{
using (BinaryWriter sigHeaderBw = new BinaryWriter(sigHeaderMem, Encoding.UTF8, true))
{
sigHeaderBw.Write((ulong)((long)headerpos - BaseOffset)); //NextHeaderOffset
sigHeaderBw.Write(headerLength); //NextHeaderSize
sigHeaderBw.Write(headerCRC); //NextHeaderCRC
sigHeaderBytes = new byte[sigHeaderMem.Length];
sigHeaderMem.Position = 0;
sigHeaderMem.Read(sigHeaderBytes, 0, sigHeaderBytes.Length);
}
}
uint sigHeaderCRC = Utils.CRC.CalculateDigest(sigHeaderBytes, 0, (uint)sigHeaderBytes.Length);
bw.BaseStream.Position = _crcOffset;
bw.Write(sigHeaderCRC); //Header CRC
bw.Write(sigHeaderBytes);
bw.BaseStream.Seek(fileEnd, SeekOrigin.Begin);
}
}
}

View File

@@ -1,91 +0,0 @@
using System;
using System.IO;
using System.Security.Permissions;
using System.Text;
using Compress.Utils;
namespace Compress.SevenZip.Structure
{
public class StreamsInfo
{
public ulong PackPosition;
public PackedStreamInfo[] PackedStreams;
public Folder[] Folders;
public void Read(BinaryReader br)
{
for (; ; )
{
HeaderProperty hp = (HeaderProperty)br.ReadByte();
switch (hp)
{
case HeaderProperty.kPackInfo:
PackedStreamInfo.Read(br, out PackPosition, out PackedStreams);
continue;
case HeaderProperty.kUnPackInfo:
Folder.ReadUnPackInfo(br, out Folders);
continue;
case HeaderProperty.kSubStreamsInfo:
Folder.ReadSubStreamsInfo(br, ref Folders);
continue;
case HeaderProperty.kEnd:
return;
default:
throw new Exception(hp.ToString());
}
}
}
public void Write(BinaryWriter bw)
{
bw.Write((byte)HeaderProperty.kMainStreamsInfo);
PackedStreamInfo.Write(bw, PackPosition, PackedStreams);
Folder.WriteUnPackInfo(bw, Folders);
Folder.WriteSubStreamsInfo(bw, Folders);
bw.Write((byte)HeaderProperty.kEnd);
}
public void WriteHeader(BinaryWriter bw)
{
PackedStreamInfo.Write(bw, PackPosition, PackedStreams);
Folder.WriteUnPackInfo(bw, Folders);
bw.Write((byte)HeaderProperty.kEnd);
}
public void Report(ref StringBuilder sb)
{
sb.AppendLine(" StreamsInfo");
sb.AppendLine(" -----------");
sb.AppendLine($" PackPosition = {PackPosition}");
if (PackedStreams == null)
{
sb.AppendLine($" PackedStreams[] = null");
}
else
{
sb.AppendLine($" PackedStreams[] = ({PackedStreams.Length})");
foreach (PackedStreamInfo psi in PackedStreams)
{
psi.Report(ref sb);
}
}
if (Folders == null)
{
sb.AppendLine($" Folders[] = null");
}
else
{
sb.AppendLine($" Folders[] = ({Folders.Length})");
foreach (Folder f in Folders)
{
f.Report(ref sb);
}
}
}
}
}

View File

@@ -1,16 +0,0 @@
using System.Text;
using Compress.Utils;
namespace Compress.SevenZip.Structure
{
public class UnpackedStreamInfo
{
public ulong UnpackedSize;
public uint? Crc;
public void Report(ref StringBuilder sb)
{
sb.AppendLine($" Crc = {Crc.ToHex()} , Size = {UnpackedSize}");
}
}
}

View File

@@ -1,384 +0,0 @@
using System.IO;
using System.Text;
namespace Compress.SevenZip
{
public enum HeaderProperty
{
kEnd,
kHeader,
kArchiveProperties,
kAdditionalStreamsInfo,
kMainStreamsInfo,
kFilesInfo,
kPackInfo,
kUnPackInfo,
kSubStreamsInfo,
kSize,
kCRC,
kFolder,
kCodersUnPackSize,
kNumUnPackStream,
kEmptyStream,
kEmptyFile,
kAnti,
kName,
kCreationTime,
kLastAccessTime,
kLastWriteTime,
kWinAttributes,
kComment,
kEncodedHeader,
kStartPos,
kDummy
}
public static class Util
{
public static readonly Encoding Enc = Encoding.GetEncoding(28591);
public static void memset(byte[] buffer, int start, byte val, int len)
{
for (int i = 0; i < len; i++)
{
buffer[start + i] = val;
}
}
public static void memcpyr(byte[] destBuffer, int destPoint, byte[] sourceBuffer, int sourcePoint, int len)
{
for (int i = len - 1; i >= 0; i--)
{
destBuffer[destPoint + i] = sourceBuffer[sourcePoint + i];
}
}
public static bool memcmp(byte[] buffer1, int offset, byte[] buffer2, int len)
{
for (int i = 0; i < len; i++)
{
if (buffer1[offset + i] != buffer2[i])
{
return false;
}
}
return true;
}
public static bool Compare(this byte[] b1, byte[] b2)
{
if ((b1 == null) || (b2 == null))
{
return false;
}
if (b1.Length != b2.Length)
{
return false;
}
for (int i = 0; i < b1.Length; i++)
{
if (b1[i] != b2[i])
{
return false;
}
}
return true;
}
public static ulong ReadEncodedUInt64(this BinaryReader br)
{
byte mask = 0x80;
int i;
byte firstByte = br.ReadByte();
ulong value = 0;
for (i = 0; i < 8; i++)
{
if ((firstByte & mask) == 0)
{
ulong highPart = (ulong)(firstByte & (mask - 1));
value += highPart << (8 * i);
return value;
}
byte b = br.ReadByte();
value |= (ulong)b << (8 * i);
mask >>= 1;
}
return value;
}
public static void WriteEncodedUInt64(this BinaryWriter bw, ulong value)
{
byte firstByte = 0;
byte mask = 0x80;
int i;
for (i = 0; i < 8; i++)
{
if (value < (ulong)1 << (7 * (i + 1)))
{
firstByte |= (byte)(value >> (8 * i));
break;
}
firstByte |= mask;
mask >>= 1;
}
bw.Write(firstByte);
for (; i > 0; i--)
{
bw.Write((byte)value);
value >>= 8;
}
}
public static string ReadName(this BinaryReader br)
{
StringBuilder stringBuilder = new StringBuilder();
for (; ; )
{
char c = (char)br.ReadUInt16();
if (c == 0)
{
return stringBuilder.ToString();
}
stringBuilder.Append(c);
}
}
public static void WriteName(this BinaryWriter bw, string name)
{
char[] chars = name.ToCharArray();
for (int i = 0; i < chars.Length; i++)
{
bw.Write((ushort)chars[i]);
}
bw.Write((ushort)0);
}
public static void UnPackCRCs(BinaryReader br, ulong numItems, out uint?[] digests)
{
bool[] digestsDefined = ReadBoolFlagsDefaultTrue(br, numItems);
digests = new uint?[numItems];
for (ulong i = 0; i < numItems; i++)
{
if (digestsDefined[i])
{
digests[i] = br.ReadUInt32();
}
}
}
public static void WritePackedCRCs(BinaryWriter bw, uint?[] digests)
{
bool[] digestsDefined = new bool[digests.Length];
for (int i = 0; i < digests.Length; i++)
{
digestsDefined[i] = digests[i] != null;
}
WriteBoolFlagsDefaultTrue(bw, digestsDefined);
for (int i = 0; i < digests.Length; i++)
{
if (digestsDefined[i])
{
bw.Write((uint)digests[i]);
}
}
}
private static bool[] ReadBoolFlagsDefaultTrue(BinaryReader br, ulong numItems)
{
byte allAreDefined = br.ReadByte();
if (allAreDefined == 0)
{
return ReadBoolFlags(br, numItems);
}
bool[] flags = new bool[numItems];
for (ulong i = 0; i < numItems; i++)
{
flags[i] = true;
}
return flags;
}
private static void WriteBoolFlagsDefaultTrue(BinaryWriter bw, bool[] bArray)
{
bool allTrue = true;
foreach (bool b in bArray)
{
allTrue &= b;
}
if (allTrue)
{
bw.Write((byte)1);
return;
}
WriteBoolFlags(bw, bArray);
}
public static bool[] ReadBoolFlags(BinaryReader br, ulong numItems)
{
byte b = 0;
byte mask = 0;
bool[] flags = new bool[numItems];
for (ulong i = 0; i < numItems; i++)
{
if (mask == 0)
{
b = br.ReadByte();
mask = 0x80;
}
flags[i] = (b & mask) != 0;
mask >>= 1;
}
return flags;
}
public static bool[] ReadBoolFlags2(BinaryReader br, ulong numItems)
{
byte allAreDefined = br.ReadByte();
if (allAreDefined == 0)
{
return ReadBoolFlags(br, numItems);
}
bool[] flags = new bool[numItems];
for (ulong i = 0; i < numItems; i++)
{
flags[i] = true;
}
return flags;
}
public static void WriteUint32Def(BinaryWriter br, uint[] values)
{
br.WriteEncodedUInt64((ulong)(values.Length * 4 + 2));
br.Write((byte)1);
br.Write((byte)0);
for (int i = 0; i < values.Length; i++)
{
br.Write(values[i]);
}
}
public static uint[] ReadUInt32Def(BinaryReader br, ulong numItems)
{
uint[] v = new uint[numItems];
bool[] defs = ReadBoolFlags2(br, numItems);
byte tmp = br.ReadByte();
for (ulong i = 0; i < numItems; i++)
{
v[i] = defs[i] ? br.ReadUInt32() : 0;
}
return v;
}
public static ulong[] ReadUInt64Def(BinaryReader br, ulong numItems)
{
ulong[] v = new ulong[numItems];
bool[] defs = ReadBoolFlags2(br, numItems);
byte tmp = br.ReadByte();
for (ulong i = 0; i < numItems; i++)
{
v[i] = defs[i] ? br.ReadUInt64() : 0;
}
return v;
}
public static void WriteBoolFlags(BinaryWriter bw, bool[] bArray)
{
bw.WriteEncodedUInt64((ulong)((bArray.Length + 7) / 8));
byte mask = 0x80;
byte tmpOut = 0;
for (int i = 0; i < bArray.Length; i++)
{
if (bArray[i])
{
tmpOut |= mask;
}
mask >>= 1;
if (mask != 0)
{
continue;
}
bw.Write(tmpOut);
mask = 0x80;
tmpOut = 0;
}
if (mask != 0x80)
{
bw.Write(tmpOut);
}
}
public static byte[] uinttobytes(uint? crc)
{
if (crc == null)
{
return null;
}
uint c = (uint)crc;
byte[] b = new byte[4];
b[0] = (byte)((c >> 24) & 0xff);
b[1] = (byte)((c >> 16) & 0xff);
b[2] = (byte)((c >> 8) & 0xff);
b[3] = (byte)((c >> 0) & 0xff);
return b;
}
public static uint? bytestouint(byte[] crc)
{
if (crc == null)
{
return null;
}
return (uint?)((crc[0] << 24) | (crc[1] << 16) | (crc[2] << 8) | (crc[3] << 0));
}
public static bool ByteArrCompare(byte[] b0, byte[] b1)
{
if ((b0 == null) || (b1 == null))
{
return false;
}
if (b0.Length != b1.Length)
{
return false;
}
for (int i = 0; i < b0.Length; i++)
{
if (b0[i] != b1[i])
{
return false;
}
}
return true;
}
}
}

View File

@@ -1,72 +0,0 @@
using System;
using System.Threading;
namespace Compress.ThreadReaders
{
public class ThreadCRC : IDisposable
{
private Utils.CRC crc;
private readonly AutoResetEvent _waitEvent;
private readonly AutoResetEvent _outEvent;
private readonly Thread _tWorker;
private byte[] _buffer;
private int _size;
private bool _finished;
public ThreadCRC()
{
crc = new Utils.CRC();
_waitEvent = new AutoResetEvent(false);
_outEvent = new AutoResetEvent(false);
_finished = false;
_tWorker = new Thread(MainLoop);
_tWorker.Start();
}
public byte[] Hash => crc.Crc32ResultB;
public void Dispose()
{
_waitEvent.Dispose();
_outEvent.Dispose();
}
private void MainLoop()
{
while (true)
{
_waitEvent.WaitOne();
if (_finished)
{
break;
}
crc.SlurpBlock(_buffer, 0, _size);
_outEvent.Set();
}
}
public void Trigger(byte[] buffer, int size)
{
_buffer = buffer;
_size = size;
_waitEvent.Set();
}
public void Wait()
{
_outEvent.WaitOne();
}
public void Finish()
{
_finished = true;
_waitEvent.Set();
_tWorker.Join();
}
}
}

View File

@@ -1,79 +0,0 @@
using System;
using System.IO;
using System.Threading;
namespace Compress.ThreadReaders
{
public class ThreadLoadBuffer : IDisposable
{
private readonly AutoResetEvent _waitEvent;
private readonly AutoResetEvent _outEvent;
private readonly Thread _tWorker;
private byte[] _buffer;
private int _size;
private readonly Stream _ds;
private bool _finished;
public bool errorState;
public int SizeRead;
public ThreadLoadBuffer(Stream ds)
{
_waitEvent = new AutoResetEvent(false);
_outEvent = new AutoResetEvent(false);
_finished = false;
_ds = ds;
errorState = false;
_tWorker = new Thread(MainLoop);
_tWorker.Start();
}
public void Dispose()
{
_waitEvent.Close();
_outEvent.Close();
}
private void MainLoop()
{
while (true)
{
_waitEvent.WaitOne();
if (_finished)
{
break;
}
try
{
SizeRead = _ds.Read(_buffer, 0, _size);
}
catch (Exception)
{
errorState = true;
}
_outEvent.Set();
}
}
public void Trigger(byte[] buffer, int size)
{
_buffer = buffer;
_size = size;
_waitEvent.Set();
}
public void Wait()
{
_outEvent.WaitOne();
}
public void Finish()
{
_finished = true;
_waitEvent.Set();
_tWorker.Join();
}
}
}

View File

@@ -1,76 +0,0 @@
using System;
using System.Security.Cryptography;
using System.Threading;
namespace Compress.ThreadReaders
{
public class ThreadMD5 : IDisposable
{
private readonly AutoResetEvent _waitEvent;
private readonly AutoResetEvent _outEvent;
private readonly Thread _tWorker;
private readonly MD5 _md5;
private byte[] _buffer;
private int _size;
private bool _finished;
public ThreadMD5()
{
_waitEvent = new AutoResetEvent(false);
_outEvent = new AutoResetEvent(false);
_finished = false;
_md5 = MD5.Create();
_tWorker = new Thread(MainLoop);
_tWorker.Start();
}
public byte[] Hash => _md5.Hash;
public void Dispose()
{
_waitEvent.Close();
_outEvent.Close();
// _md5.Dispose();
}
private void MainLoop()
{
while (true)
{
_waitEvent.WaitOne();
if (_finished)
{
break;
}
_md5.TransformBlock(_buffer, 0, _size, null, 0);
_outEvent.Set();
}
byte[] tmp = new byte[0];
_md5.TransformFinalBlock(tmp, 0, 0);
}
public void Trigger(byte[] buffer, int size)
{
_buffer = buffer;
_size = size;
_waitEvent.Set();
}
public void Wait()
{
_outEvent.WaitOne();
}
public void Finish()
{
_finished = true;
_waitEvent.Set();
_tWorker.Join();
}
}
}

View File

@@ -1,76 +0,0 @@
using System;
using System.Security.Cryptography;
using System.Threading;
namespace Compress.ThreadReaders
{
public class ThreadSHA1 : IDisposable
{
private readonly AutoResetEvent _waitEvent;
private readonly AutoResetEvent _outEvent;
private readonly Thread _tWorker;
private readonly SHA1 _sha1;
private byte[] _buffer;
private int _size;
private bool _finished;
public ThreadSHA1()
{
_waitEvent = new AutoResetEvent(false);
_outEvent = new AutoResetEvent(false);
_finished = false;
_sha1 = SHA1.Create();
_tWorker = new Thread(MainLoop);
_tWorker.Start();
}
public byte[] Hash => _sha1.Hash;
public void Dispose()
{
_waitEvent.Close();
_outEvent.Close();
// _sha1.Dispose();
}
private void MainLoop()
{
while (true)
{
_waitEvent.WaitOne();
if (_finished)
{
break;
}
_sha1.TransformBlock(_buffer, 0, _size, null, 0);
_outEvent.Set();
}
byte[] tmp = new byte[0];
_sha1.TransformFinalBlock(tmp, 0, 0);
}
public void Trigger(byte[] buffer, int size)
{
_buffer = buffer;
_size = size;
_waitEvent.Set();
}
public void Wait()
{
_outEvent.WaitOne();
}
public void Finish()
{
_finished = true;
_waitEvent.Set();
_tWorker.Join();
}
}
}

View File

@@ -1,125 +0,0 @@
using System;
namespace Compress.Utils
{
public class CRC
{
public static readonly uint[] CRC32Lookup;
private uint _crc;
private long _totalBytesRead;
static CRC()
{
const uint polynomial = 0xEDB88320;
const int crcNumTables = 8;
unchecked
{
CRC32Lookup = new uint[256 * crcNumTables];
int i;
for (i = 0; i < 256; i++)
{
uint r = (uint)i;
for (int j = 0; j < 8; j++)
{
r = (r >> 1) ^ (polynomial & ~((r & 1) - 1));
}
CRC32Lookup[i] = r;
}
for (; i < 256 * crcNumTables; i++)
{
uint r = CRC32Lookup[i - 256];
CRC32Lookup[i] = CRC32Lookup[r & 0xFF] ^ (r >> 8);
}
}
}
public CRC()
{
Reset();
}
public void Reset()
{
_totalBytesRead = 0;
_crc = 0xffffffffu;
}
internal void UpdateCRC(int inCh)
{
_crc = (_crc >> 8) ^ CRC32Lookup[(byte)_crc ^ ((byte)inCh)];
}
public void SlurpBlock(byte[] block, int offset, int count)
{
_totalBytesRead += count;
uint crc = _crc;
for (; (offset & 7) != 0 && count != 0; count--)
crc = (crc >> 8) ^ CRC32Lookup[(byte)crc ^ block[offset++]];
if (count >= 8)
{
int end = (count - 8) & ~7;
count -= end;
end += offset;
while (offset != end)
{
crc ^= (uint)(block[offset] + (block[offset + 1] << 8) + (block[offset + 2] << 16) + (block[offset + 3] << 24));
uint high = (uint)(block[offset + 4] + (block[offset + 5] << 8) + (block[offset + 6] << 16) + (block[offset + 7] << 24));
offset += 8;
crc = CRC32Lookup[(byte)crc + 0x700]
^ CRC32Lookup[(byte)(crc >>= 8) + 0x600]
^ CRC32Lookup[(byte)(crc >>= 8) + 0x500]
^ CRC32Lookup[ /*(byte)*/(crc >> 8) + 0x400]
^ CRC32Lookup[(byte)high + 0x300]
^ CRC32Lookup[(byte)(high >>= 8) + 0x200]
^ CRC32Lookup[(byte)(high >>= 8) + 0x100]
^ CRC32Lookup[ /*(byte)*/(high >> 8) + 0x000];
}
}
while (count-- != 0)
{
crc = (crc >> 8) ^ CRC32Lookup[(byte)crc ^ block[offset++]];
}
_crc = crc;
}
public byte[] Crc32ResultB
{
get
{
byte[] result = BitConverter.GetBytes(~_crc);
Array.Reverse(result);
return result;
}
}
public Int32 Crc32Result => unchecked((Int32)(~_crc));
public uint Crc32ResultU => ~_crc;
public Int64 TotalBytesRead => _totalBytesRead;
public static uint CalculateDigest(byte[] data, uint offset, uint size)
{
CRC crc = new CRC();
// crc.Init();
crc.SlurpBlock(data, (int)offset, (int)size);
return crc.Crc32ResultU;
}
public static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size)
{
return (CalculateDigest(data, offset, size) == digest);
}
}
}

View File

@@ -1,343 +0,0 @@
using System;
namespace Compress.Utils
{
class CRCStream
{
}
/// <summary>
/// A Stream that calculates a CRC32 (a checksum) on all bytes read,
/// or on all bytes written.
/// </summary>
///
/// <remarks>
/// <para>
/// This class can be used to verify the CRC of a ZipEntry when
/// reading from a stream, or to calculate a CRC when writing to a
/// stream. The stream should be used to either read, or write, but
/// not both. If you intermix reads and writes, the results are not
/// defined.
/// </para>
///
/// <para>
/// This class is intended primarily for use internally by the
/// DotNetZip library.
/// </para>
/// </remarks>
public class CrcCalculatorStream : System.IO.Stream, System.IDisposable
{
private static readonly Int64 UnsetLengthLimit = -99;
internal System.IO.Stream _innerStream;
private CRC _Crc32;
private Int64 _lengthLimit = -99;
private bool _leaveOpen;
/// <summary>
/// The default constructor.
/// </summary>
/// <remarks>
/// <para>
/// Instances returned from this constructor will leave the underlying
/// stream open upon Close(). The stream uses the default CRC32
/// algorithm, which implies a polynomial of 0xEDB88320.
/// </para>
/// </remarks>
/// <param name="stream">The underlying stream</param>
public CrcCalculatorStream(System.IO.Stream stream)
: this(true, UnsetLengthLimit, stream, null)
{
}
/// <summary>
/// The constructor allows the caller to specify how to handle the
/// underlying stream at close.
/// </summary>
/// <remarks>
/// <para>
/// The stream uses the default CRC32 algorithm, which implies a
/// polynomial of 0xEDB88320.
/// </para>
/// </remarks>
/// <param name="stream">The underlying stream</param>
/// <param name="leaveOpen">true to leave the underlying stream
/// open upon close of the <c>CrcCalculatorStream</c>; false otherwise.</param>
public CrcCalculatorStream(System.IO.Stream stream, bool leaveOpen)
: this(leaveOpen, UnsetLengthLimit, stream, null)
{
}
/// <summary>
/// A constructor allowing the specification of the length of the stream
/// to read.
/// </summary>
/// <remarks>
/// <para>
/// The stream uses the default CRC32 algorithm, which implies a
/// polynomial of 0xEDB88320.
/// </para>
/// <para>
/// Instances returned from this constructor will leave the underlying
/// stream open upon Close().
/// </para>
/// </remarks>
/// <param name="stream">The underlying stream</param>
/// <param name="length">The length of the stream to slurp</param>
public CrcCalculatorStream(System.IO.Stream stream, Int64 length)
: this(true, length, stream, null)
{
if (length < 0)
throw new ArgumentException("length");
}
/// <summary>
/// A constructor allowing the specification of the length of the stream
/// to read, as well as whether to keep the underlying stream open upon
/// Close().
/// </summary>
/// <remarks>
/// <para>
/// The stream uses the default CRC32 algorithm, which implies a
/// polynomial of 0xEDB88320.
/// </para>
/// </remarks>
/// <param name="stream">The underlying stream</param>
/// <param name="length">The length of the stream to slurp</param>
/// <param name="leaveOpen">true to leave the underlying stream
/// open upon close of the <c>CrcCalculatorStream</c>; false otherwise.</param>
public CrcCalculatorStream(System.IO.Stream stream, Int64 length, bool leaveOpen)
: this(leaveOpen, length, stream, null)
{
if (length < 0)
throw new ArgumentException("length");
}
/// <summary>
/// A constructor allowing the specification of the length of the stream
/// to read, as well as whether to keep the underlying stream open upon
/// Close(), and the CRC32 instance to use.
/// </summary>
/// <remarks>
/// <para>
/// The stream uses the specified CRC32 instance, which allows the
/// application to specify how the CRC gets calculated.
/// </para>
/// </remarks>
/// <param name="stream">The underlying stream</param>
/// <param name="length">The length of the stream to slurp</param>
/// <param name="leaveOpen">true to leave the underlying stream
/// open upon close of the <c>CrcCalculatorStream</c>; false otherwise.</param>
/// <param name="crc32">the CRC32 instance to use to calculate the CRC32</param>
public CrcCalculatorStream(System.IO.Stream stream, Int64 length, bool leaveOpen,
CRC crc32)
: this(leaveOpen, length, stream, crc32)
{
if (length < 0)
throw new ArgumentException("length");
}
// This ctor is private - no validation is done here. This is to allow the use
// of a (specific) negative value for the _lengthLimit, to indicate that there
// is no length set. So we validate the length limit in those ctors that use an
// explicit param, otherwise we don't validate, because it could be our special
// value.
private CrcCalculatorStream
(bool leaveOpen, Int64 length, System.IO.Stream stream, CRC crc32)
: base()
{
_innerStream = stream;
_Crc32 = crc32 ?? new CRC();
_lengthLimit = length;
_leaveOpen = leaveOpen;
}
/// <summary>
/// Gets the total number of bytes run through the CRC32 calculator.
/// </summary>
///
/// <remarks>
/// This is either the total number of bytes read, or the total number of
/// bytes written, depending on the direction of this stream.
/// </remarks>
public Int64 TotalBytesSlurped
{
get { return _Crc32.TotalBytesRead; }
}
/// <summary>
/// Provides the current CRC for all blocks slurped in.
/// </summary>
/// <remarks>
/// <para>
/// The running total of the CRC is kept as data is written or read
/// through the stream. read this property after all reads or writes to
/// get an accurate CRC for the entire stream.
/// </para>
/// </remarks>
public Int32 Crc
{
get { return _Crc32.Crc32Result; }
}
/// <summary>
/// Indicates whether the underlying stream will be left open when the
/// <c>CrcCalculatorStream</c> is Closed.
/// </summary>
/// <remarks>
/// <para>
/// Set this at any point before calling <see cref="Close()"/>.
/// </para>
/// </remarks>
public bool LeaveOpen
{
get { return _leaveOpen; }
set { _leaveOpen = value; }
}
/// <summary>
/// Read from the stream
/// </summary>
/// <param name="buffer">the buffer to read</param>
/// <param name="offset">the offset at which to start</param>
/// <param name="count">the number of bytes to read</param>
/// <returns>the number of bytes actually read</returns>
public override int Read(byte[] buffer, int offset, int count)
{
int bytesToRead = count;
// Need to limit the # of bytes returned, if the stream is intended to have
// a definite length. This is especially useful when returning a stream for
// the uncompressed data directly to the application. The app won't
// necessarily read only the UncompressedSize number of bytes. For example
// wrapping the stream returned from OpenReader() into a StreadReader() and
// calling ReadToEnd() on it, We can "over-read" the zip data and get a
// corrupt string. The length limits that, prevents that problem.
if (_lengthLimit != UnsetLengthLimit)
{
if (_Crc32.TotalBytesRead >= _lengthLimit) return 0; // EOF
Int64 bytesRemaining = _lengthLimit - _Crc32.TotalBytesRead;
if (bytesRemaining < count) bytesToRead = (int)bytesRemaining;
}
int n = _innerStream.Read(buffer, offset, bytesToRead);
if (n > 0) _Crc32.SlurpBlock(buffer, offset, n);
return n;
}
/// <summary>
/// Write to the stream.
/// </summary>
/// <param name="buffer">the buffer from which to write</param>
/// <param name="offset">the offset at which to start writing</param>
/// <param name="count">the number of bytes to write</param>
public override void Write(byte[] buffer, int offset, int count)
{
if (count > 0) _Crc32.SlurpBlock(buffer, offset, count);
_innerStream.Write(buffer, offset, count);
}
/// <summary>
/// Indicates whether the stream supports reading.
/// </summary>
public override bool CanRead
{
get { return _innerStream.CanRead; }
}
/// <summary>
/// Indicates whether the stream supports seeking.
/// </summary>
/// <remarks>
/// <para>
/// Always returns false.
/// </para>
/// </remarks>
public override bool CanSeek
{
get { return false; }
}
/// <summary>
/// Indicates whether the stream supports writing.
/// </summary>
public override bool CanWrite
{
get { return _innerStream.CanWrite; }
}
/// <summary>
/// Flush the stream.
/// </summary>
public override void Flush()
{
_innerStream.Flush();
}
/// <summary>
/// Returns the length of the underlying stream.
/// </summary>
public override long Length
{
get
{
if (_lengthLimit == CrcCalculatorStream.UnsetLengthLimit)
return _innerStream.Length;
else return _lengthLimit;
}
}
/// <summary>
/// The getter for this property returns the total bytes read.
/// If you use the setter, it will throw
/// <see cref="NotSupportedException"/>.
/// </summary>
public override long Position
{
get { return _Crc32.TotalBytesRead; }
set { throw new NotSupportedException(); }
}
/// <summary>
/// Seeking is not supported on this stream. This method always throws
/// <see cref="NotSupportedException"/>
/// </summary>
/// <param name="offset">N/A</param>
/// <param name="origin">N/A</param>
/// <returns>N/A</returns>
public override long Seek(long offset, System.IO.SeekOrigin origin)
{
throw new NotSupportedException();
}
/// <summary>
/// This method always throws
/// <see cref="NotSupportedException"/>
/// </summary>
/// <param name="value">N/A</param>
public override void SetLength(long value)
{
throw new NotSupportedException();
}
void IDisposable.Dispose()
{
Close();
}
/// <summary>
/// Closes the stream.
/// </summary>
public override void Close()
{
base.Close();
if (!_leaveOpen)
_innerStream.Close();
}
}
}

View File

@@ -1,39 +0,0 @@
using RVIO;
namespace Compress.Utils
{
public static class DirUtil
{
public static void CreateDirForFile(string sFilename)
{
string strTemp = Path.GetDirectoryName(sFilename);
if (string.IsNullOrEmpty(strTemp))
{
return;
}
if (Directory.Exists(strTemp))
{
return;
}
while ((strTemp.Length > 0) && !Directory.Exists(strTemp))
{
int pos = strTemp.LastIndexOf(Path.DirectorySeparatorChar);
if (pos < 0)
{
pos = 0;
}
strTemp = strTemp.Substring(0, pos);
}
while (sFilename.IndexOf(Path.DirectorySeparatorChar, strTemp.Length + 1) > 0)
{
strTemp = sFilename.Substring(0, sFilename.IndexOf(Path.DirectorySeparatorChar, strTemp.Length + 1));
Directory.CreateDirectory(strTemp);
}
}
}
}

View File

@@ -1,43 +0,0 @@

namespace Compress.Utils
{
public static class Reporter
{
public static string ToArrayString(this ulong[] arr)
{
if (arr == null)
return "NULL";
string ret = $"({arr.Length}) " + arr[0].ToString();
for (int i = 1; i < arr.Length; i++)
{
ret += "," + arr[i].ToString();
}
return ret;
}
public static string ToArrayString(this byte[] arr)
{
if (arr == null)
return "NULL";
string ret = $"({arr.Length}) " + arr[0].ToString("X2");
for (int i = 1; i < arr.Length; i++)
{
ret += "," + arr[i].ToString("X2");
}
return ret;
}
public static string ToHex(this uint? v)
{
return v == null ? "NULL" : ((uint)v).ToString("X8");
}
public static string ToHex(this ulong? v)
{
return v == null ? "NULL" : ((ulong)v).ToString("X8");
}
}
}

View File

@@ -1,53 +0,0 @@
using System;
namespace Compress
{
public enum ZipReturn
{
ZipGood,
ZipFileLocked,
ZipFileCountError,
ZipSignatureError,
ZipExtraDataOnEndOfZip,
ZipUnsupportedCompression,
ZipLocalFileHeaderError,
ZipCentralDirError,
ZipEndOfCentralDirectoryError,
Zip64EndOfCentralDirError,
Zip64EndOfCentralDirectoryLocatorError,
ZipReadingFromOutputFile,
ZipWritingToInputFile,
ZipErrorGettingDataStream,
ZipCRCDecodeError,
ZipDecodeError,
ZipFileNameToLong,
ZipFileAlreadyOpen,
ZipCannotFastOpen,
ZipErrorOpeningFile,
ZipErrorFileNotFound,
ZipErrorReadingFile,
ZipErrorTimeStamp,
ZipErrorRollBackFile,
ZipTryingToAccessADirectory,
ZipErrorWritingToOutputStream,
ZipUntested
}
public enum ZipOpenType
{
Closed,
OpenRead,
OpenWrite,
OpenFakeWrite
}
[Flags]
public enum ZipStatus
{
None = 0x0,
TrrntZip = 0x1,
ExtraData = 0x2,
Trrnt7Zip = 0x4
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,436 +0,0 @@
// Inftree.cs
// ------------------------------------------------------------------
//
// Copyright (c) 2009 Dino Chiesa and Microsoft Corporation.
// All rights reserved.
//
// This code module is part of DotNetZip, a zipfile class library.
//
// ------------------------------------------------------------------
//
// This code is licensed under the Microsoft Public License.
// See the file License.txt for the license details.
// More info on: http://dotnetzip.codeplex.com
//
// ------------------------------------------------------------------
//
// last saved (in emacs):
// Time-stamp: <2009-October-28 12:43:54>
//
// ------------------------------------------------------------------
//
// This module defines classes used in decompression. This code is derived
// from the jzlib implementation of zlib. In keeping with the license for jzlib,
// the copyright to that code is below.
//
// ------------------------------------------------------------------
//
// Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in
// the documentation and/or other materials provided with the distribution.
//
// 3. The names of the authors may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
// INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// -----------------------------------------------------------------------
//
// This program is based on zlib-1.1.3; credit to authors
// Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
// and contributors of zlib.
//
// -----------------------------------------------------------------------
using System;
namespace Compress.ZipFile.ZLib
{
sealed class InfTree
{
private const int MANY = 1440;
private const int Z_OK = 0;
private const int Z_STREAM_END = 1;
private const int Z_NEED_DICT = 2;
private const int Z_ERRNO = -1;
private const int Z_STREAM_ERROR = -2;
private const int Z_DATA_ERROR = -3;
private const int Z_MEM_ERROR = -4;
private const int Z_BUF_ERROR = -5;
private const int Z_VERSION_ERROR = -6;
internal const int fixed_bl = 9;
internal const int fixed_bd = 5;
//UPGRADE_NOTE: Final was removed from the declaration of 'fixed_tl'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
internal static readonly int[] fixed_tl = new int[]{96, 7, 256, 0, 8, 80, 0, 8, 16, 84, 8, 115, 82, 7, 31, 0, 8, 112, 0, 8, 48, 0, 9, 192, 80, 7, 10, 0, 8, 96, 0, 8, 32, 0, 9, 160, 0, 8, 0, 0, 8, 128, 0, 8, 64, 0, 9, 224, 80, 7, 6, 0, 8, 88, 0, 8, 24, 0, 9, 144, 83, 7, 59, 0, 8, 120, 0, 8, 56, 0, 9, 208, 81, 7, 17, 0, 8, 104, 0, 8, 40, 0, 9, 176, 0, 8, 8, 0, 8, 136, 0, 8, 72, 0, 9, 240, 80, 7, 4, 0, 8, 84, 0, 8, 20, 85, 8, 227, 83, 7, 43, 0, 8, 116, 0, 8, 52, 0, 9, 200, 81, 7, 13, 0, 8, 100, 0, 8, 36, 0, 9, 168, 0, 8, 4, 0, 8, 132, 0, 8, 68, 0, 9, 232, 80, 7, 8, 0, 8, 92, 0, 8, 28, 0, 9, 152, 84, 7, 83, 0, 8, 124, 0, 8, 60, 0, 9, 216, 82, 7, 23, 0, 8, 108, 0, 8, 44, 0, 9, 184, 0, 8, 12, 0, 8, 140, 0, 8, 76, 0, 9, 248, 80, 7, 3, 0, 8, 82, 0, 8, 18, 85, 8, 163, 83, 7, 35, 0, 8, 114, 0, 8, 50, 0, 9, 196, 81, 7, 11, 0, 8, 98, 0, 8, 34, 0, 9, 164, 0, 8, 2, 0, 8, 130, 0, 8, 66, 0, 9, 228, 80, 7, 7, 0, 8, 90, 0, 8, 26, 0, 9, 148, 84, 7, 67, 0, 8, 122, 0, 8, 58, 0, 9, 212, 82, 7, 19, 0, 8, 106, 0, 8, 42, 0, 9, 180, 0, 8, 10, 0, 8, 138, 0, 8, 74, 0, 9, 244, 80, 7, 5, 0, 8, 86, 0, 8, 22, 192, 8, 0, 83, 7, 51, 0, 8, 118, 0, 8, 54, 0, 9, 204, 81, 7, 15, 0, 8, 102, 0, 8, 38, 0, 9, 172, 0, 8, 6, 0, 8, 134, 0, 8, 70, 0, 9, 236, 80, 7, 9, 0, 8, 94, 0, 8, 30, 0, 9, 156, 84, 7, 99, 0, 8, 126, 0, 8, 62, 0, 9, 220, 82, 7, 27, 0, 8, 110, 0, 8, 46, 0, 9, 188, 0, 8, 14, 0, 8, 142, 0, 8, 78, 0, 9, 252, 96, 7, 256, 0, 8, 81, 0, 8, 17, 85, 8, 131, 82, 7, 31, 0, 8, 113, 0, 8, 49, 0, 9, 194, 80, 7, 10, 0, 8, 97, 0, 8, 33, 0, 9, 162, 0, 8, 1, 0, 8, 129, 0, 8, 65, 0, 9, 226, 80, 7, 6, 0, 8, 89, 0, 8, 25, 0, 9, 146, 83, 7, 59, 0, 8, 121, 0, 8, 57, 0, 9, 210, 81, 7, 17, 0, 8, 105, 0, 8, 41, 0, 9, 178, 0, 8, 9, 0, 8, 137, 0, 8, 73, 0, 9, 242, 80, 7, 4, 0, 8, 85, 0, 8, 21, 80, 8, 258, 83, 7, 43, 0, 8, 117, 0, 8, 53, 0, 9, 202, 81, 7, 13, 0, 8, 101, 0, 8, 37, 0, 9, 170, 0, 8, 5, 0, 8, 133, 0, 8, 69, 0, 9, 234, 80, 7, 8, 0, 8, 93, 0, 8, 29, 0, 9, 154, 84, 7, 83, 0, 8, 125, 0, 8, 61, 0, 9, 218, 82, 7, 23, 0, 8, 109, 0, 8, 45, 0, 9, 186,
0, 8, 13, 0, 8, 141, 0, 8, 77, 0, 9, 250, 80, 7, 3, 0, 8, 83, 0, 8, 19, 85, 8, 195, 83, 7, 35, 0, 8, 115, 0, 8, 51, 0, 9, 198, 81, 7, 11, 0, 8, 99, 0, 8, 35, 0, 9, 166, 0, 8, 3, 0, 8, 131, 0, 8, 67, 0, 9, 230, 80, 7, 7, 0, 8, 91, 0, 8, 27, 0, 9, 150, 84, 7, 67, 0, 8, 123, 0, 8, 59, 0, 9, 214, 82, 7, 19, 0, 8, 107, 0, 8, 43, 0, 9, 182, 0, 8, 11, 0, 8, 139, 0, 8, 75, 0, 9, 246, 80, 7, 5, 0, 8, 87, 0, 8, 23, 192, 8, 0, 83, 7, 51, 0, 8, 119, 0, 8, 55, 0, 9, 206, 81, 7, 15, 0, 8, 103, 0, 8, 39, 0, 9, 174, 0, 8, 7, 0, 8, 135, 0, 8, 71, 0, 9, 238, 80, 7, 9, 0, 8, 95, 0, 8, 31, 0, 9, 158, 84, 7, 99, 0, 8, 127, 0, 8, 63, 0, 9, 222, 82, 7, 27, 0, 8, 111, 0, 8, 47, 0, 9, 190, 0, 8, 15, 0, 8, 143, 0, 8, 79, 0, 9, 254, 96, 7, 256, 0, 8, 80, 0, 8, 16, 84, 8, 115, 82, 7, 31, 0, 8, 112, 0, 8, 48, 0, 9, 193, 80, 7, 10, 0, 8, 96, 0, 8, 32, 0, 9, 161, 0, 8, 0, 0, 8, 128, 0, 8, 64, 0, 9, 225, 80, 7, 6, 0, 8, 88, 0, 8, 24, 0, 9, 145, 83, 7, 59, 0, 8, 120, 0, 8, 56, 0, 9, 209, 81, 7, 17, 0, 8, 104, 0, 8, 40, 0, 9, 177, 0, 8, 8, 0, 8, 136, 0, 8, 72, 0, 9, 241, 80, 7, 4, 0, 8, 84, 0, 8, 20, 85, 8, 227, 83, 7, 43, 0, 8, 116, 0, 8, 52, 0, 9, 201, 81, 7, 13, 0, 8, 100, 0, 8, 36, 0, 9, 169, 0, 8, 4, 0, 8, 132, 0, 8, 68, 0, 9, 233, 80, 7, 8, 0, 8, 92, 0, 8, 28, 0, 9, 153, 84, 7, 83, 0, 8, 124, 0, 8, 60, 0, 9, 217, 82, 7, 23, 0, 8, 108, 0, 8, 44, 0, 9, 185, 0, 8, 12, 0, 8, 140, 0, 8, 76, 0, 9, 249, 80, 7, 3, 0, 8, 82, 0, 8, 18, 85, 8, 163, 83, 7, 35, 0, 8, 114, 0, 8, 50, 0, 9, 197, 81, 7, 11, 0, 8, 98, 0, 8, 34, 0, 9, 165, 0, 8, 2, 0, 8, 130, 0, 8, 66, 0, 9, 229, 80, 7, 7, 0, 8, 90, 0, 8, 26, 0, 9, 149, 84, 7, 67, 0, 8, 122, 0, 8, 58, 0, 9, 213, 82, 7, 19, 0, 8, 106, 0, 8, 42, 0, 9, 181, 0, 8, 10, 0, 8, 138, 0, 8, 74, 0, 9, 245, 80, 7, 5, 0, 8, 86, 0, 8, 22, 192, 8, 0, 83, 7, 51, 0, 8, 118, 0, 8, 54, 0, 9, 205, 81, 7, 15, 0, 8, 102, 0, 8, 38, 0, 9, 173, 0, 8, 6, 0, 8, 134, 0, 8, 70, 0, 9, 237, 80, 7, 9, 0, 8, 94, 0, 8, 30, 0, 9, 157, 84, 7, 99, 0, 8, 126, 0, 8, 62, 0, 9, 221, 82, 7, 27, 0, 8, 110, 0, 8, 46, 0, 9, 189, 0, 8,
14, 0, 8, 142, 0, 8, 78, 0, 9, 253, 96, 7, 256, 0, 8, 81, 0, 8, 17, 85, 8, 131, 82, 7, 31, 0, 8, 113, 0, 8, 49, 0, 9, 195, 80, 7, 10, 0, 8, 97, 0, 8, 33, 0, 9, 163, 0, 8, 1, 0, 8, 129, 0, 8, 65, 0, 9, 227, 80, 7, 6, 0, 8, 89, 0, 8, 25, 0, 9, 147, 83, 7, 59, 0, 8, 121, 0, 8, 57, 0, 9, 211, 81, 7, 17, 0, 8, 105, 0, 8, 41, 0, 9, 179, 0, 8, 9, 0, 8, 137, 0, 8, 73, 0, 9, 243, 80, 7, 4, 0, 8, 85, 0, 8, 21, 80, 8, 258, 83, 7, 43, 0, 8, 117, 0, 8, 53, 0, 9, 203, 81, 7, 13, 0, 8, 101, 0, 8, 37, 0, 9, 171, 0, 8, 5, 0, 8, 133, 0, 8, 69, 0, 9, 235, 80, 7, 8, 0, 8, 93, 0, 8, 29, 0, 9, 155, 84, 7, 83, 0, 8, 125, 0, 8, 61, 0, 9, 219, 82, 7, 23, 0, 8, 109, 0, 8, 45, 0, 9, 187, 0, 8, 13, 0, 8, 141, 0, 8, 77, 0, 9, 251, 80, 7, 3, 0, 8, 83, 0, 8, 19, 85, 8, 195, 83, 7, 35, 0, 8, 115, 0, 8, 51, 0, 9, 199, 81, 7, 11, 0, 8, 99, 0, 8, 35, 0, 9, 167, 0, 8, 3, 0, 8, 131, 0, 8, 67, 0, 9, 231, 80, 7, 7, 0, 8, 91, 0, 8, 27, 0, 9, 151, 84, 7, 67, 0, 8, 123, 0, 8, 59, 0, 9, 215, 82, 7, 19, 0, 8, 107, 0, 8, 43, 0, 9, 183, 0, 8, 11, 0, 8, 139, 0, 8, 75, 0, 9, 247, 80, 7, 5, 0, 8, 87, 0, 8, 23, 192, 8, 0, 83, 7, 51, 0, 8, 119, 0, 8, 55, 0, 9, 207, 81, 7, 15, 0, 8, 103, 0, 8, 39, 0, 9, 175, 0, 8, 7, 0, 8, 135, 0, 8, 71, 0, 9, 239, 80, 7, 9, 0, 8, 95, 0, 8, 31, 0, 9, 159, 84, 7, 99, 0, 8, 127, 0, 8, 63, 0, 9, 223, 82, 7, 27, 0, 8, 111, 0, 8, 47, 0, 9, 191, 0, 8, 15, 0, 8, 143, 0, 8, 79, 0, 9, 255};
//UPGRADE_NOTE: Final was removed from the declaration of 'fixed_td'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
internal static readonly int[] fixed_td = new int[] { 80, 5, 1, 87, 5, 257, 83, 5, 17, 91, 5, 4097, 81, 5, 5, 89, 5, 1025, 85, 5, 65, 93, 5, 16385, 80, 5, 3, 88, 5, 513, 84, 5, 33, 92, 5, 8193, 82, 5, 9, 90, 5, 2049, 86, 5, 129, 192, 5, 24577, 80, 5, 2, 87, 5, 385, 83, 5, 25, 91, 5, 6145, 81, 5, 7, 89, 5, 1537, 85, 5, 97, 93, 5, 24577, 80, 5, 4, 88, 5, 769, 84, 5, 49, 92, 5, 12289, 82, 5, 13, 90, 5, 3073, 86, 5, 193, 192, 5, 24577 };
// Tables for deflate from PKZIP's appnote.txt.
//UPGRADE_NOTE: Final was removed from the declaration of 'cplens'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
internal static readonly int[] cplens = new int[] { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 };
// see note #13 above about 258
//UPGRADE_NOTE: Final was removed from the declaration of 'cplext'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
internal static readonly int[] cplext = new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112 };
//UPGRADE_NOTE: Final was removed from the declaration of 'cpdist'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
internal static readonly int[] cpdist = new int[] { 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577 };
//UPGRADE_NOTE: Final was removed from the declaration of 'cpdext'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
internal static readonly int[] cpdext = new int[] { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 };
// If BMAX needs to be larger than 16, then h and x[] should be uLong.
internal const int BMAX = 15; // maximum bit length of any code
internal int[] hn = null; // hufts used in space
internal int[] v = null; // work area for huft_build
internal int[] c = null; // bit length count table
internal int[] r = null; // table entry for structure assignment
internal int[] u = null; // table stack
internal int[] x = null; // bit offsets, then code stack
private int huft_build(int[] b, int bindex, int n, int s, int[] d, int[] e, int[] t, int[] m, int[] hp, int[] hn, int[] v)
{
// Given a list of code lengths and a maximum table size, make a set of
// tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR
// if the given code set is incomplete (the tables are still built in this
// case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of
// lengths), or Z_MEM_ERROR if not enough memory.
int a; // counter for codes of length k
int f; // i repeats in table every f entries
int g; // maximum code length
int h; // table level
int i; // counter, current code
int j; // counter
int k; // number of bits in current code
int l; // bits per table (returned in m)
int mask; // (1 << w) - 1, to avoid cc -O bug on HP
int p; // pointer into c[], b[], or v[]
int q; // points to current table
int w; // bits before this table == (l * h)
int xp; // pointer into x
int y; // number of dummy codes added
int z; // number of entries in current table
// Generate counts for each bit length
p = 0; i = n;
do
{
c[b[bindex + p]]++; p++; i--; // assume all entries <= BMAX
}
while (i != 0);
if (c[0] == n)
{
// null input--all zero length codes
t[0] = -1;
m[0] = 0;
return Z_OK;
}
// Find minimum and maximum length, bound *m by those
l = m[0];
for (j = 1; j <= BMAX; j++)
if (c[j] != 0)
break;
k = j; // minimum code length
if (l < j)
{
l = j;
}
for (i = BMAX; i != 0; i--)
{
if (c[i] != 0)
break;
}
g = i; // maximum code length
if (l > i)
{
l = i;
}
m[0] = l;
// Adjust last length count to fill out codes, if needed
for (y = 1 << j; j < i; j++, y <<= 1)
{
if ((y -= c[j]) < 0)
{
return Z_DATA_ERROR;
}
}
if ((y -= c[i]) < 0)
{
return Z_DATA_ERROR;
}
c[i] += y;
// Generate starting offsets into the value table for each length
x[1] = j = 0;
p = 1; xp = 2;
while (--i != 0)
{
// note that i == g from above
x[xp] = (j += c[p]);
xp++;
p++;
}
// Make a table of values in order of bit lengths
i = 0; p = 0;
do
{
if ((j = b[bindex + p]) != 0)
{
v[x[j]++] = i;
}
p++;
}
while (++i < n);
n = x[g]; // set n to length of v
// Generate the Huffman codes and for each, make the table entries
x[0] = i = 0; // first Huffman code is zero
p = 0; // grab values in bit order
h = -1; // no tables yet--level -1
w = -l; // bits decoded == (l * h)
u[0] = 0; // just to keep compilers happy
q = 0; // ditto
z = 0; // ditto
// go through the bit lengths (k already is bits in shortest code)
for (; k <= g; k++)
{
a = c[k];
while (a-- != 0)
{
// here i is the Huffman code of length k bits for value *p
// make tables up to required level
while (k > w + l)
{
h++;
w += l; // previous table always l bits
// compute minimum size table less than or equal to l bits
z = g - w;
z = (z > l) ? l : z; // table size upper limit
if ((f = 1 << (j = k - w)) > a + 1)
{
// try a k-w bit table
// too few codes for k-w bit table
f -= (a + 1); // deduct codes from patterns left
xp = k;
if (j < z)
{
while (++j < z)
{
// try smaller tables up to z bits
if ((f <<= 1) <= c[++xp])
break; // enough codes to use up j bits
f -= c[xp]; // else deduct codes from patterns
}
}
}
z = 1 << j; // table entries for j-bit table
// allocate new table
if (hn[0] + z > MANY)
{
// (note: doesn't matter for fixed)
return Z_DATA_ERROR; // overflow of MANY
}
u[h] = q = hn[0]; // DEBUG
hn[0] += z;
// connect to last table, if there is one
if (h != 0)
{
x[h] = i; // save pattern for backing up
r[0] = (sbyte)j; // bits in this table
r[1] = (sbyte)l; // bits to dump before this table
j = SharedUtils.URShift(i, (w - l));
r[2] = (int)(q - u[h - 1] - j); // offset to this table
Array.Copy(r, 0, hp, (u[h - 1] + j) * 3, 3); // connect to last table
}
else
{
t[0] = q; // first table is returned result
}
}
// set up table entry in r
r[1] = (sbyte)(k - w);
if (p >= n)
{
r[0] = 128 + 64; // out of values--invalid code
}
else if (v[p] < s)
{
r[0] = (sbyte)(v[p] < 256 ? 0 : 32 + 64); // 256 is end-of-block
r[2] = v[p++]; // simple code is just the value
}
else
{
r[0] = (sbyte)(e[v[p] - s] + 16 + 64); // non-simple--look up in lists
r[2] = d[v[p++] - s];
}
// fill code-like entries with r
f = 1 << (k - w);
for (j = SharedUtils.URShift(i, w); j < z; j += f)
{
Array.Copy(r, 0, hp, (q + j) * 3, 3);
}
// backwards increment the k-bit code i
for (j = 1 << (k - 1); (i & j) != 0; j = SharedUtils.URShift(j, 1))
{
i ^= j;
}
i ^= j;
// backup over finished tables
mask = (1 << w) - 1; // needed on HP, cc -O bug
while ((i & mask) != x[h])
{
h--; // don't need to update q
w -= l;
mask = (1 << w) - 1;
}
}
}
// Return Z_BUF_ERROR if we were given an incomplete table
return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
}
internal int inflate_trees_bits(int[] c, int[] bb, int[] tb, int[] hp, ZlibCodec z)
{
int result;
initWorkArea(19);
hn[0] = 0;
result = huft_build(c, 0, 19, 19, null, null, tb, bb, hp, hn, v);
if (result == Z_DATA_ERROR)
{
z.Message = "oversubscribed dynamic bit lengths tree";
}
else if (result == Z_BUF_ERROR || bb[0] == 0)
{
z.Message = "incomplete dynamic bit lengths tree";
result = Z_DATA_ERROR;
}
return result;
}
internal int inflate_trees_dynamic(int nl, int nd, int[] c, int[] bl, int[] bd, int[] tl, int[] td, int[] hp, ZlibCodec z)
{
int result;
// build literal/length tree
initWorkArea(288);
hn[0] = 0;
result = huft_build(c, 0, nl, 257, cplens, cplext, tl, bl, hp, hn, v);
if (result != Z_OK || bl[0] == 0)
{
if (result == Z_DATA_ERROR)
{
z.Message = "oversubscribed literal/length tree";
}
else if (result != Z_MEM_ERROR)
{
z.Message = "incomplete literal/length tree";
result = Z_DATA_ERROR;
}
return result;
}
// build distance tree
initWorkArea(288);
result = huft_build(c, nl, nd, 0, cpdist, cpdext, td, bd, hp, hn, v);
if (result != Z_OK || (bd[0] == 0 && nl > 257))
{
if (result == Z_DATA_ERROR)
{
z.Message = "oversubscribed distance tree";
}
else if (result == Z_BUF_ERROR)
{
z.Message = "incomplete distance tree";
result = Z_DATA_ERROR;
}
else if (result != Z_MEM_ERROR)
{
z.Message = "empty distance tree with lengths";
result = Z_DATA_ERROR;
}
return result;
}
return Z_OK;
}
internal static int inflate_trees_fixed(int[] bl, int[] bd, int[][] tl, int[][] td, ZlibCodec z)
{
bl[0] = fixed_bl;
bd[0] = fixed_bd;
tl[0] = fixed_tl;
td[0] = fixed_td;
return Z_OK;
}
private void initWorkArea(int vsize)
{
if (hn == null)
{
hn = new int[1];
v = new int[vsize];
c = new int[BMAX + 1];
r = new int[3];
u = new int[BMAX];
x = new int[BMAX + 1];
}
else
{
if (v.Length < vsize)
{
v = new int[vsize];
}
Array.Clear(v, 0, vsize);
Array.Clear(c, 0, BMAX + 1);
r[0] = 0; r[1] = 0; r[2] = 0;
// for(int i=0; i<BMAX; i++){u[i]=0;}
//Array.Copy(c, 0, u, 0, BMAX);
Array.Clear(u, 0, BMAX);
// for(int i=0; i<BMAX+1; i++){x[i]=0;}
//Array.Copy(c, 0, x, 0, BMAX + 1);
Array.Clear(x, 0, BMAX + 1);
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,422 +0,0 @@
// Tree.cs
// ------------------------------------------------------------------
//
// Copyright (c) 2009 Dino Chiesa and Microsoft Corporation.
// All rights reserved.
//
// This code module is part of DotNetZip, a zipfile class library.
//
// ------------------------------------------------------------------
//
// This code is licensed under the Microsoft Public License.
// See the file License.txt for the license details.
// More info on: http://dotnetzip.codeplex.com
//
// ------------------------------------------------------------------
//
// last saved (in emacs):
// Time-stamp: <2009-October-28 13:29:50>
//
// ------------------------------------------------------------------
//
// This module defines classes for zlib compression and
// decompression. This code is derived from the jzlib implementation of
// zlib. In keeping with the license for jzlib, the copyright to that
// code is below.
//
// ------------------------------------------------------------------
//
// Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in
// the documentation and/or other materials provided with the distribution.
//
// 3. The names of the authors may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
// INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// -----------------------------------------------------------------------
//
// This program is based on zlib-1.1.3; credit to authors
// Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
// and contributors of zlib.
//
// -----------------------------------------------------------------------
namespace Compress.ZipFile.ZLib
{
sealed class Tree
{
private static readonly int HEAP_SIZE = (2 * InternalConstants.L_CODES + 1);
// extra bits for each length code
internal static readonly int[] ExtraLengthBits = new int[]
{
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0
};
// extra bits for each distance code
internal static readonly int[] ExtraDistanceBits = new int[]
{
0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13
};
// extra bits for each bit length code
internal static readonly int[] extra_blbits = new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7 };
internal static readonly sbyte[] bl_order = new sbyte[] { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
// The lengths of the bit length codes are sent in order of decreasing
// probability, to avoid transmitting the lengths for unused bit
// length codes.
internal const int Buf_size = 8 * 2;
// see definition of array dist_code below
//internal const int DIST_CODE_LEN = 512;
private static readonly sbyte[] _dist_code = new sbyte[]
{
0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7,
8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9,
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
0, 0, 16, 17, 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21,
22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
};
internal static readonly sbyte[] LengthCode = new sbyte[]
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11,
12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15,
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17,
18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
};
internal static readonly int[] LengthBase = new int[]
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28,
32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 0
};
internal static readonly int[] DistanceBase = new int[]
{
0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192,
256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
};
/// <summary>
/// Map from a distance to a distance code.
/// </summary>
/// <remarks>
/// No side effects. _dist_code[256] and _dist_code[257] are never used.
/// </remarks>
internal static int DistanceCode(int dist)
{
return (dist < 256)
? _dist_code[dist]
: _dist_code[256 + SharedUtils.URShift(dist, 7)];
}
internal short[] dyn_tree; // the dynamic tree
internal int max_code; // largest code with non zero frequency
internal StaticTree staticTree; // the corresponding static tree
// Compute the optimal bit lengths for a tree and update the total bit length
// for the current block.
// IN assertion: the fields freq and dad are set, heap[heap_max] and
// above are the tree nodes sorted by increasing frequency.
// OUT assertions: the field len is set to the optimal bit length, the
// array bl_count contains the frequencies for each bit length.
// The length opt_len is updated; static_len is also updated if stree is
// not null.
internal void gen_bitlen(DeflateManager s)
{
short[] tree = dyn_tree;
short[] stree = staticTree.treeCodes;
int[] extra = staticTree.extraBits;
int base_Renamed = staticTree.extraBase;
int max_length = staticTree.maxLength;
int h; // heap index
int n, m; // iterate over the tree elements
int bits; // bit length
int xbits; // extra bits
short f; // frequency
int overflow = 0; // number of elements with bit length too large
for (bits = 0; bits <= InternalConstants.MAX_BITS; bits++)
s.bl_count[bits] = 0;
// In a first pass, compute the optimal bit lengths (which may
// overflow in the case of the bit length tree).
tree[s.heap[s.heap_max] * 2 + 1] = 0; // root of the heap
for (h = s.heap_max + 1; h < HEAP_SIZE; h++)
{
n = s.heap[h];
bits = tree[tree[n * 2 + 1] * 2 + 1] + 1;
if (bits > max_length)
{
bits = max_length; overflow++;
}
tree[n * 2 + 1] = (short)bits;
// We overwrite tree[n*2+1] which is no longer needed
if (n > max_code)
continue; // not a leaf node
s.bl_count[bits]++;
xbits = 0;
if (n >= base_Renamed)
xbits = extra[n - base_Renamed];
f = tree[n * 2];
s.opt_len += f * (bits + xbits);
if (stree != null)
s.static_len += f * (stree[n * 2 + 1] + xbits);
}
if (overflow == 0)
return;
// This happens for example on obj2 and pic of the Calgary corpus
// Find the first bit length which could increase:
do
{
bits = max_length - 1;
while (s.bl_count[bits] == 0)
bits--;
s.bl_count[bits]--; // move one leaf down the tree
s.bl_count[bits + 1] = (short)(s.bl_count[bits + 1] + 2); // move one overflow item as its brother
s.bl_count[max_length]--;
// The brother of the overflow item also moves one step up,
// but this does not affect bl_count[max_length]
overflow -= 2;
}
while (overflow > 0);
for (bits = max_length; bits != 0; bits--)
{
n = s.bl_count[bits];
while (n != 0)
{
m = s.heap[--h];
if (m > max_code)
continue;
if (tree[m * 2 + 1] != bits)
{
s.opt_len = (int)(s.opt_len + ((long)bits - (long)tree[m * 2 + 1]) * (long)tree[m * 2]);
tree[m * 2 + 1] = (short)bits;
}
n--;
}
}
}
// Construct one Huffman tree and assigns the code bit strings and lengths.
// Update the total bit length for the current block.
// IN assertion: the field freq is set for all tree elements.
// OUT assertions: the fields len and code are set to the optimal bit length
// and corresponding code. The length opt_len is updated; static_len is
// also updated if stree is not null. The field max_code is set.
internal void build_tree(DeflateManager s)
{
short[] tree = dyn_tree;
short[] stree = staticTree.treeCodes;
int elems = staticTree.elems;
int n, m; // iterate over heap elements
int max_code = -1; // largest code with non zero frequency
int node; // new node being created
// Construct the initial heap, with least frequent element in
// heap[1]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
// heap[0] is not used.
s.heap_len = 0;
s.heap_max = HEAP_SIZE;
for (n = 0; n < elems; n++)
{
if (tree[n * 2] != 0)
{
s.heap[++s.heap_len] = max_code = n;
s.depth[n] = 0;
}
else
{
tree[n * 2 + 1] = 0;
}
}
// The pkzip format requires that at least one distance code exists,
// and that at least one bit should be sent even if there is only one
// possible code. So to avoid special checks later on we force at least
// two codes of non zero frequency.
while (s.heap_len < 2)
{
node = s.heap[++s.heap_len] = (max_code < 2 ? ++max_code : 0);
tree[node * 2] = 1;
s.depth[node] = 0;
s.opt_len--;
if (stree != null)
s.static_len -= stree[node * 2 + 1];
// node is 0 or 1 so it does not have extra bits
}
this.max_code = max_code;
// The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
// establish sub-heaps of increasing lengths:
for (n = s.heap_len / 2; n >= 1; n--)
s.pqdownheap(tree, n);
// Construct the Huffman tree by repeatedly combining the least two
// frequent nodes.
node = elems; // next internal node of the tree
do
{
// n = node of least frequency
n = s.heap[1];
s.heap[1] = s.heap[s.heap_len--];
s.pqdownheap(tree, 1);
m = s.heap[1]; // m = node of next least frequency
s.heap[--s.heap_max] = n; // keep the nodes sorted by frequency
s.heap[--s.heap_max] = m;
// Create a new node father of n and m
tree[node * 2] = unchecked((short)(tree[n * 2] + tree[m * 2]));
s.depth[node] = (sbyte)(System.Math.Max((byte)s.depth[n], (byte)s.depth[m]) + 1);
tree[n * 2 + 1] = tree[m * 2 + 1] = (short)node;
// and insert the new node in the heap
s.heap[1] = node++;
s.pqdownheap(tree, 1);
}
while (s.heap_len >= 2);
s.heap[--s.heap_max] = s.heap[1];
// At this point, the fields freq and dad are set. We can now
// generate the bit lengths.
gen_bitlen(s);
// The field len is now set, we can generate the bit codes
gen_codes(tree, max_code, s.bl_count);
}
// Generate the codes for a given tree and bit counts (which need not be
// optimal).
// IN assertion: the array bl_count contains the bit length statistics for
// the given tree and the field len is set for all tree elements.
// OUT assertion: the field code is set for all tree elements of non
// zero code length.
internal static void gen_codes(short[] tree, int max_code, short[] bl_count)
{
short[] next_code = new short[InternalConstants.MAX_BITS + 1]; // next code value for each bit length
short code = 0; // running code value
int bits; // bit index
int n; // code index
// The distribution counts are first used to generate the code values
// without bit reversal.
for (bits = 1; bits <= InternalConstants.MAX_BITS; bits++)
unchecked
{
next_code[bits] = code = (short)((code + bl_count[bits - 1]) << 1);
}
// Check that the bit counts in bl_count are consistent. The last code
// must be all ones.
//Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
// "inconsistent bit counts");
//Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
for (n = 0; n <= max_code; n++)
{
int len = tree[n * 2 + 1];
if (len == 0)
continue;
// Now reverse the bits
tree[n * 2] = unchecked((short)(bi_reverse(next_code[len]++, len)));
}
}
// Reverse the first len bits of a code, using straightforward code (a faster
// method would use a table)
// IN assertion: 1 <= len <= 15
internal static int bi_reverse(int code, int len)
{
int res = 0;
do
{
res |= code & 1;
code >>= 1; //SharedUtils.URShift(code, 1);
res <<= 1;
}
while (--len > 0);
return res >> 1;
}
}
}

View File

@@ -1,480 +0,0 @@
// Zlib.cs
// ------------------------------------------------------------------
//
// Copyright (c) 2009-2011 Dino Chiesa and Microsoft Corporation.
// All rights reserved.
//
// This code module is part of DotNetZip, a zipfile class library.
//
// ------------------------------------------------------------------
//
// This code is licensed under the Microsoft Public License.
// See the file License.txt for the license details.
// More info on: http://dotnetzip.codeplex.com
//
// ------------------------------------------------------------------
//
// Last Saved: <2011-August-03 19:52:28>
//
// ------------------------------------------------------------------
//
// This module defines classes for ZLIB compression and
// decompression. This code is derived from the jzlib implementation of
// zlib, but significantly modified. The object model is not the same,
// and many of the behaviors are new or different. Nonetheless, in
// keeping with the license for jzlib, the copyright to that code is
// included below.
//
// ------------------------------------------------------------------
//
// The following notice applies to jzlib:
//
// Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in
// the documentation and/or other materials provided with the distribution.
//
// 3. The names of the authors may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
// INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// -----------------------------------------------------------------------
//
// jzlib is based on zlib-1.1.3.
//
// The following notice applies to zlib:
//
// -----------------------------------------------------------------------
//
// Copyright (C) 1995-2004 Jean-loup Gailly and Mark Adler
//
// The ZLIB software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
// Jean-loup Gailly jloup@gzip.org
// Mark Adler madler@alumni.caltech.edu
//
// -----------------------------------------------------------------------
using System.Runtime.InteropServices;
namespace Compress.ZipFile.ZLib
{
/// <summary>
/// Describes how to flush the current deflate operation.
/// </summary>
/// <remarks>
/// The different FlushType values are useful when using a Deflate in a streaming application.
/// </remarks>
public enum FlushType
{
/// <summary>No flush at all.</summary>
None = 0,
/// <summary>Closes the current block, but doesn't flush it to
/// the output. Used internally only in hypothetical
/// scenarios. This was supposed to be removed by Zlib, but it is
/// still in use in some edge cases.
/// </summary>
Partial,
/// <summary>
/// Use this during compression to specify that all pending output should be
/// flushed to the output buffer and the output should be aligned on a byte
/// boundary. You might use this in a streaming communication scenario, so that
/// the decompressor can get all input data available so far. When using this
/// with a ZlibCodec, <c>AvailableBytesIn</c> will be zero after the call if
/// enough output space has been provided before the call. Flushing will
/// degrade compression and so it should be used only when necessary.
/// </summary>
Sync,
/// <summary>
/// Use this during compression to specify that all output should be flushed, as
/// with <c>FlushType.Sync</c>, but also, the compression state should be reset
/// so that decompression can restart from this point if previous compressed
/// data has been damaged or if random access is desired. Using
/// <c>FlushType.Full</c> too often can significantly degrade the compression.
/// </summary>
Full,
/// <summary>Signals the end of the compression/decompression stream.</summary>
Finish,
}
/// <summary>
/// The compression level to be used when using a DeflateStream or ZlibStream with CompressionMode.Compress.
/// </summary>
public enum CompressionLevel
{
/// <summary>
/// None means that the data will be simply stored, with no change at all.
/// If you are producing ZIPs for use on Mac OSX, be aware that archives produced with CompressionLevel.None
/// cannot be opened with the default zip reader. Use a different CompressionLevel.
/// </summary>
None = 0,
/// <summary>
/// Same as None.
/// </summary>
Level0 = 0,
/// <summary>
/// The fastest but least effective compression.
/// </summary>
BestSpeed = 1,
/// <summary>
/// A synonym for BestSpeed.
/// </summary>
Level1 = 1,
/// <summary>
/// A little slower, but better, than level 1.
/// </summary>
Level2 = 2,
/// <summary>
/// A little slower, but better, than level 2.
/// </summary>
Level3 = 3,
/// <summary>
/// A little slower, but better, than level 3.
/// </summary>
Level4 = 4,
/// <summary>
/// A little slower than level 4, but with better compression.
/// </summary>
Level5 = 5,
/// <summary>
/// The default compression level, with a good balance of speed and compression efficiency.
/// </summary>
Default = 6,
/// <summary>
/// A synonym for Default.
/// </summary>
Level6 = 6,
/// <summary>
/// Pretty good compression!
/// </summary>
Level7 = 7,
/// <summary>
/// Better compression than Level7!
/// </summary>
Level8 = 8,
/// <summary>
/// The "best" compression, where best means greatest reduction in size of the input data stream.
/// This is also the slowest compression.
/// </summary>
BestCompression = 9,
/// <summary>
/// A synonym for BestCompression.
/// </summary>
Level9 = 9,
}
/// <summary>
/// Describes options for how the compression algorithm is executed. Different strategies
/// work better on different sorts of data. The strategy parameter can affect the compression
/// ratio and the speed of compression but not the correctness of the compresssion.
/// </summary>
public enum CompressionStrategy
{
/// <summary>
/// The default strategy is probably the best for normal data.
/// </summary>
Default = 0,
/// <summary>
/// The <c>Filtered</c> strategy is intended to be used most effectively with data produced by a
/// filter or predictor. By this definition, filtered data consists mostly of small
/// values with a somewhat random distribution. In this case, the compression algorithm
/// is tuned to compress them better. The effect of <c>Filtered</c> is to force more Huffman
/// coding and less string matching; it is a half-step between <c>Default</c> and <c>HuffmanOnly</c>.
/// </summary>
Filtered = 1,
/// <summary>
/// Using <c>HuffmanOnly</c> will force the compressor to do Huffman encoding only, with no
/// string matching.
/// </summary>
HuffmanOnly = 2,
}
/// <summary>
/// An enum to specify the direction of transcoding - whether to compress or decompress.
/// </summary>
public enum CompressionMode
{
/// <summary>
/// Used to specify that the stream should compress the data.
/// </summary>
Compress = 0,
/// <summary>
/// Used to specify that the stream should decompress the data.
/// </summary>
Decompress = 1,
}
/// <summary>
/// A general purpose exception class for exceptions in the Zlib library.
/// </summary>
[Guid("ebc25cf6-9120-4283-b972-0e5520d0000E")]
public class ZlibException : System.Exception
{
/// <summary>
/// The ZlibException class captures exception information generated
/// by the Zlib library.
/// </summary>
public ZlibException()
: base()
{
}
/// <summary>
/// This ctor collects a message attached to the exception.
/// </summary>
/// <param name="s">the message for the exception.</param>
public ZlibException(System.String s)
: base(s)
{
}
}
internal class SharedUtils
{
/// <summary>
/// Performs an unsigned bitwise right shift with the specified number
/// </summary>
/// <param name="number">Number to operate on</param>
/// <param name="bits">Ammount of bits to shift</param>
/// <returns>The resulting number from the shift operation</returns>
public static int URShift(int number, int bits)
{
return (int)((uint)number >> bits);
}
}
internal static class InternalConstants
{
internal static readonly int MAX_BITS = 15;
internal static readonly int BL_CODES = 19;
internal static readonly int D_CODES = 30;
internal static readonly int LITERALS = 256;
internal static readonly int LENGTH_CODES = 29;
internal static readonly int L_CODES = (LITERALS + 1 + LENGTH_CODES);
// Bit length codes must not exceed MAX_BL_BITS bits
internal static readonly int MAX_BL_BITS = 7;
// repeat previous bit length 3-6 times (2 bits of repeat count)
internal static readonly int REP_3_6 = 16;
// repeat a zero length 3-10 times (3 bits of repeat count)
internal static readonly int REPZ_3_10 = 17;
// repeat a zero length 11-138 times (7 bits of repeat count)
internal static readonly int REPZ_11_138 = 18;
}
internal sealed class StaticTree
{
internal static readonly short[] lengthAndLiteralsTreeCodes = new short[] {
12, 8, 140, 8, 76, 8, 204, 8, 44, 8, 172, 8, 108, 8, 236, 8,
28, 8, 156, 8, 92, 8, 220, 8, 60, 8, 188, 8, 124, 8, 252, 8,
2, 8, 130, 8, 66, 8, 194, 8, 34, 8, 162, 8, 98, 8, 226, 8,
18, 8, 146, 8, 82, 8, 210, 8, 50, 8, 178, 8, 114, 8, 242, 8,
10, 8, 138, 8, 74, 8, 202, 8, 42, 8, 170, 8, 106, 8, 234, 8,
26, 8, 154, 8, 90, 8, 218, 8, 58, 8, 186, 8, 122, 8, 250, 8,
6, 8, 134, 8, 70, 8, 198, 8, 38, 8, 166, 8, 102, 8, 230, 8,
22, 8, 150, 8, 86, 8, 214, 8, 54, 8, 182, 8, 118, 8, 246, 8,
14, 8, 142, 8, 78, 8, 206, 8, 46, 8, 174, 8, 110, 8, 238, 8,
30, 8, 158, 8, 94, 8, 222, 8, 62, 8, 190, 8, 126, 8, 254, 8,
1, 8, 129, 8, 65, 8, 193, 8, 33, 8, 161, 8, 97, 8, 225, 8,
17, 8, 145, 8, 81, 8, 209, 8, 49, 8, 177, 8, 113, 8, 241, 8,
9, 8, 137, 8, 73, 8, 201, 8, 41, 8, 169, 8, 105, 8, 233, 8,
25, 8, 153, 8, 89, 8, 217, 8, 57, 8, 185, 8, 121, 8, 249, 8,
5, 8, 133, 8, 69, 8, 197, 8, 37, 8, 165, 8, 101, 8, 229, 8,
21, 8, 149, 8, 85, 8, 213, 8, 53, 8, 181, 8, 117, 8, 245, 8,
13, 8, 141, 8, 77, 8, 205, 8, 45, 8, 173, 8, 109, 8, 237, 8,
29, 8, 157, 8, 93, 8, 221, 8, 61, 8, 189, 8, 125, 8, 253, 8,
19, 9, 275, 9, 147, 9, 403, 9, 83, 9, 339, 9, 211, 9, 467, 9,
51, 9, 307, 9, 179, 9, 435, 9, 115, 9, 371, 9, 243, 9, 499, 9,
11, 9, 267, 9, 139, 9, 395, 9, 75, 9, 331, 9, 203, 9, 459, 9,
43, 9, 299, 9, 171, 9, 427, 9, 107, 9, 363, 9, 235, 9, 491, 9,
27, 9, 283, 9, 155, 9, 411, 9, 91, 9, 347, 9, 219, 9, 475, 9,
59, 9, 315, 9, 187, 9, 443, 9, 123, 9, 379, 9, 251, 9, 507, 9,
7, 9, 263, 9, 135, 9, 391, 9, 71, 9, 327, 9, 199, 9, 455, 9,
39, 9, 295, 9, 167, 9, 423, 9, 103, 9, 359, 9, 231, 9, 487, 9,
23, 9, 279, 9, 151, 9, 407, 9, 87, 9, 343, 9, 215, 9, 471, 9,
55, 9, 311, 9, 183, 9, 439, 9, 119, 9, 375, 9, 247, 9, 503, 9,
15, 9, 271, 9, 143, 9, 399, 9, 79, 9, 335, 9, 207, 9, 463, 9,
47, 9, 303, 9, 175, 9, 431, 9, 111, 9, 367, 9, 239, 9, 495, 9,
31, 9, 287, 9, 159, 9, 415, 9, 95, 9, 351, 9, 223, 9, 479, 9,
63, 9, 319, 9, 191, 9, 447, 9, 127, 9, 383, 9, 255, 9, 511, 9,
0, 7, 64, 7, 32, 7, 96, 7, 16, 7, 80, 7, 48, 7, 112, 7,
8, 7, 72, 7, 40, 7, 104, 7, 24, 7, 88, 7, 56, 7, 120, 7,
4, 7, 68, 7, 36, 7, 100, 7, 20, 7, 84, 7, 52, 7, 116, 7,
3, 8, 131, 8, 67, 8, 195, 8, 35, 8, 163, 8, 99, 8, 227, 8
};
internal static readonly short[] distTreeCodes = new short[] {
0, 5, 16, 5, 8, 5, 24, 5, 4, 5, 20, 5, 12, 5, 28, 5,
2, 5, 18, 5, 10, 5, 26, 5, 6, 5, 22, 5, 14, 5, 30, 5,
1, 5, 17, 5, 9, 5, 25, 5, 5, 5, 21, 5, 13, 5, 29, 5,
3, 5, 19, 5, 11, 5, 27, 5, 7, 5, 23, 5 };
internal static readonly StaticTree Literals;
internal static readonly StaticTree Distances;
internal static readonly StaticTree BitLengths;
internal short[] treeCodes; // static tree or null
internal int[] extraBits; // extra bits for each code or null
internal int extraBase; // base index for extra_bits
internal int elems; // max number of elements in the tree
internal int maxLength; // max bit length for the codes
private StaticTree(short[] treeCodes, int[] extraBits, int extraBase, int elems, int maxLength)
{
this.treeCodes = treeCodes;
this.extraBits = extraBits;
this.extraBase = extraBase;
this.elems = elems;
this.maxLength = maxLength;
}
static StaticTree()
{
Literals = new StaticTree(lengthAndLiteralsTreeCodes, Tree.ExtraLengthBits, InternalConstants.LITERALS + 1, InternalConstants.L_CODES, InternalConstants.MAX_BITS);
Distances = new StaticTree(distTreeCodes, Tree.ExtraDistanceBits, 0, InternalConstants.D_CODES, InternalConstants.MAX_BITS);
BitLengths = new StaticTree(null, Tree.extra_blbits, 0, InternalConstants.BL_CODES, InternalConstants.MAX_BL_BITS);
}
}
/// <summary>
/// Computes an Adler-32 checksum.
/// </summary>
/// <remarks>
/// The Adler checksum is similar to a CRC checksum, but faster to compute, though less
/// reliable. It is used in producing RFC1950 compressed streams. The Adler checksum
/// is a required part of the "ZLIB" standard. Applications will almost never need to
/// use this class directly.
/// </remarks>
///
/// <exclude/>
public sealed class Adler
{
// largest prime smaller than 65536
private static readonly uint BASE = 65521;
// NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
private static readonly int NMAX = 5552;
/// <summary>
/// Calculates the Adler32 checksum.
/// </summary>
/// <remarks>
/// <para>
/// This is used within ZLIB. You probably don't need to use this directly.
/// </para>
/// </remarks>
/// <example>
/// To compute an Adler32 checksum on a byte array:
/// <code>
/// var adler = Adler.Adler32(0, null, 0, 0);
/// adler = Adler.Adler32(adler, buffer, index, length);
/// </code>
/// </example>
public static uint Adler32(uint adler, byte[] buf, int index, int len)
{
if (buf == null)
return 1;
uint s1 = (uint)(adler & 0xffff);
uint s2 = (uint)((adler >> 16) & 0xffff);
while (len > 0)
{
int k = len < NMAX ? len : NMAX;
len -= k;
while (k >= 16)
{
//s1 += (buf[index++] & 0xff); s2 += s1;
s1 += buf[index++]; s2 += s1;
s1 += buf[index++]; s2 += s1;
s1 += buf[index++]; s2 += s1;
s1 += buf[index++]; s2 += s1;
s1 += buf[index++]; s2 += s1;
s1 += buf[index++]; s2 += s1;
s1 += buf[index++]; s2 += s1;
s1 += buf[index++]; s2 += s1;
s1 += buf[index++]; s2 += s1;
s1 += buf[index++]; s2 += s1;
s1 += buf[index++]; s2 += s1;
s1 += buf[index++]; s2 += s1;
s1 += buf[index++]; s2 += s1;
s1 += buf[index++]; s2 += s1;
s1 += buf[index++]; s2 += s1;
s1 += buf[index++]; s2 += s1;
k -= 16;
}
if (k != 0)
{
do
{
s1 += buf[index++];
s2 += s1;
}
while (--k != 0);
}
s1 %= BASE;
s2 %= BASE;
}
return (uint)((s2 << 16) | s1);
}
}
}

View File

@@ -1,556 +0,0 @@
// ZlibBaseStream.cs
// ------------------------------------------------------------------
//
// Copyright (c) 2009 Dino Chiesa and Microsoft Corporation.
// All rights reserved.
//
// This code module is part of DotNetZip, a zipfile class library.
//
// ------------------------------------------------------------------
//
// This code is licensed under the Microsoft Public License.
// See the file License.txt for the license details.
// More info on: http://dotnetzip.codeplex.com
//
// ------------------------------------------------------------------
//
// last saved (in emacs):
// Time-stamp: <2011-August-06 21:22:38>
//
// ------------------------------------------------------------------
//
// This module defines the ZlibBaseStream class, which is an intnernal
// base class for DeflateStream, ZlibStream and GZipStream.
//
// ------------------------------------------------------------------
using System;
using System.IO;
namespace Compress.ZipFile.ZLib
{
public enum ZlibStreamFlavor { ZLIB = 1950, DEFLATE = 1951, GZIP = 1952 }
public class ZlibBaseStream : System.IO.Stream
{
protected internal ZlibCodec _z = null; // deferred init... new ZlibCodec();
protected internal StreamMode _streamMode = StreamMode.Undefined;
protected internal FlushType _flushMode;
protected internal ZlibStreamFlavor _flavor;
protected internal CompressionMode _compressionMode;
protected internal CompressionLevel _level;
protected internal bool _leaveOpen;
protected internal byte[] _workingBuffer;
protected internal int _bufferSize = ZlibConstants.WorkingBufferSizeDefault;
protected internal byte[] _buf1 = new byte[1];
protected internal System.IO.Stream _stream;
protected internal CompressionStrategy Strategy = CompressionStrategy.Default;
// workitem 7159
Compress.Utils.CRC crc;
protected internal string _GzipFileName;
protected internal string _GzipComment;
protected internal DateTime _GzipMtime;
protected internal int _gzipHeaderByteCount;
internal int Crc32 { get { if (crc == null) return 0; return crc.Crc32Result; } }
public ZlibBaseStream(System.IO.Stream stream,
CompressionMode compressionMode,
CompressionLevel level,
ZlibStreamFlavor flavor,
bool leaveOpen)
: base()
{
this._flushMode = FlushType.None;
//this._workingBuffer = new byte[WORKING_BUFFER_SIZE_DEFAULT];
this._stream = stream;
this._leaveOpen = leaveOpen;
this._compressionMode = compressionMode;
this._flavor = flavor;
this._level = level;
// workitem 7159
if (flavor == ZlibStreamFlavor.GZIP)
{
this.crc = new Compress.Utils.CRC();
}
}
protected internal bool _wantCompress
{
get
{
return (this._compressionMode == CompressionMode.Compress);
}
}
private ZlibCodec z
{
get
{
if (_z == null)
{
bool wantRfc1950Header = (this._flavor == ZlibStreamFlavor.ZLIB);
_z = new ZlibCodec();
if (this._compressionMode == CompressionMode.Decompress)
{
_z.InitializeInflate(wantRfc1950Header);
}
else
{
_z.Strategy = Strategy;
_z.InitializeDeflate(this._level, wantRfc1950Header);
}
}
return _z;
}
}
private byte[] workingBuffer
{
get
{
if (_workingBuffer == null)
_workingBuffer = new byte[_bufferSize];
return _workingBuffer;
}
}
public override void Write(System.Byte[] buffer, int offset, int count)
{
// workitem 7159
// calculate the CRC on the unccompressed data (before writing)
if (crc != null)
crc.SlurpBlock(buffer, offset, count);
if (_streamMode == StreamMode.Undefined)
_streamMode = StreamMode.Writer;
else if (_streamMode != StreamMode.Writer)
throw new ZlibException("Cannot Write after Reading.");
if (count == 0)
return;
// first reference of z property will initialize the private var _z
z.InputBuffer = buffer;
_z.NextIn = offset;
_z.AvailableBytesIn = count;
bool done = false;
do
{
_z.OutputBuffer = workingBuffer;
_z.NextOut = 0;
_z.AvailableBytesOut = _workingBuffer.Length;
int rc = (_wantCompress)
? _z.Deflate(_flushMode)
: _z.Inflate(_flushMode);
if (rc != ZlibConstants.Z_OK && rc != ZlibConstants.Z_STREAM_END)
throw new ZlibException((_wantCompress ? "de" : "in") + "flating: " + _z.Message);
//if (_workingBuffer.Length - _z.AvailableBytesOut > 0)
_stream.Write(_workingBuffer, 0, _workingBuffer.Length - _z.AvailableBytesOut);
done = _z.AvailableBytesIn == 0 && _z.AvailableBytesOut != 0;
// If GZIP and de-compress, we're done when 8 bytes remain.
if (_flavor == ZlibStreamFlavor.GZIP && !_wantCompress)
done = (_z.AvailableBytesIn == 8 && _z.AvailableBytesOut != 0);
}
while (!done);
}
private void finish()
{
if (_z == null) return;
if (_streamMode == StreamMode.Writer)
{
bool done = false;
do
{
_z.OutputBuffer = workingBuffer;
_z.NextOut = 0;
_z.AvailableBytesOut = _workingBuffer.Length;
int rc = (_wantCompress)
? _z.Deflate(FlushType.Finish)
: _z.Inflate(FlushType.Finish);
if (rc != ZlibConstants.Z_STREAM_END && rc != ZlibConstants.Z_OK)
{
string verb = (_wantCompress ? "de" : "in") + "flating";
if (_z.Message == null)
throw new ZlibException(String.Format("{0}: (rc = {1})", verb, rc));
else
throw new ZlibException(verb + ": " + _z.Message);
}
if (_workingBuffer.Length - _z.AvailableBytesOut > 0)
{
_stream.Write(_workingBuffer, 0, _workingBuffer.Length - _z.AvailableBytesOut);
}
done = _z.AvailableBytesIn == 0 && _z.AvailableBytesOut != 0;
// If GZIP and de-compress, we're done when 8 bytes remain.
if (_flavor == ZlibStreamFlavor.GZIP && !_wantCompress)
done = (_z.AvailableBytesIn == 8 && _z.AvailableBytesOut != 0);
}
while (!done);
Flush();
// workitem 7159
if (_flavor == ZlibStreamFlavor.GZIP)
{
if (_wantCompress)
{
// Emit the GZIP trailer: CRC32 and size mod 2^32
int c1 = crc.Crc32Result;
_stream.Write(BitConverter.GetBytes(c1), 0, 4);
int c2 = (Int32)(crc.TotalBytesRead & 0x00000000FFFFFFFF);
_stream.Write(BitConverter.GetBytes(c2), 0, 4);
}
else
{
throw new ZlibException("Writing with decompression is not supported.");
}
}
}
// workitem 7159
else if (_streamMode == StreamMode.Reader)
{
if (_flavor == ZlibStreamFlavor.GZIP)
{
if (!_wantCompress)
{
// workitem 8501: handle edge case (decompress empty stream)
if (_z.TotalBytesOut == 0L)
return;
// Read and potentially verify the GZIP trailer:
// CRC32 and size mod 2^32
byte[] trailer = new byte[8];
// workitems 8679 & 12554
if (_z.AvailableBytesIn < 8)
{
// Make sure we have read to the end of the stream
Array.Copy(_z.InputBuffer, _z.NextIn, trailer, 0, _z.AvailableBytesIn);
int bytesNeeded = 8 - _z.AvailableBytesIn;
int bytesRead = _stream.Read(trailer,
_z.AvailableBytesIn,
bytesNeeded);
if (bytesNeeded != bytesRead)
{
throw new ZlibException(String.Format("Missing or incomplete GZIP trailer. Expected 8 bytes, got {0}.",
_z.AvailableBytesIn + bytesRead));
}
}
else
{
Array.Copy(_z.InputBuffer, _z.NextIn, trailer, 0, trailer.Length);
}
Int32 crc32_expected = BitConverter.ToInt32(trailer, 0);
Int32 crc32_actual = crc.Crc32Result;
Int32 isize_expected = BitConverter.ToInt32(trailer, 4);
Int32 isize_actual = (Int32)(_z.TotalBytesOut & 0x00000000FFFFFFFF);
if (crc32_actual != crc32_expected)
throw new ZlibException(String.Format("Bad CRC32 in GZIP trailer. (actual({0:X8})!=expected({1:X8}))", crc32_actual, crc32_expected));
if (isize_actual != isize_expected)
throw new ZlibException(String.Format("Bad size in GZIP trailer. (actual({0})!=expected({1}))", isize_actual, isize_expected));
}
else
{
throw new ZlibException("Reading with compression is not supported.");
}
}
}
}
private void end()
{
if (z == null)
return;
if (_wantCompress)
{
_z.EndDeflate();
}
else
{
_z.EndInflate();
}
_z = null;
}
public override void Close()
{
if (_stream == null) return;
try
{
finish();
}
finally
{
end();
if (!_leaveOpen) _stream.Close();
_stream = null;
}
}
public override void Flush()
{
_stream.Flush();
}
public override System.Int64 Seek(System.Int64 offset, System.IO.SeekOrigin origin)
{
return _stream.Seek(offset, origin);
}
public override void SetLength(System.Int64 value)
{
_stream.SetLength(value);
}
private bool nomoreinput = false;
private string ReadZeroTerminatedString()
{
var list = new System.Collections.Generic.List<byte>();
bool done = false;
do
{
// workitem 7740
int n = _stream.Read(_buf1, 0, 1);
if (n != 1)
throw new ZlibException("Unexpected EOF reading GZIP header.");
else
{
if (_buf1[0] == 0)
done = true;
else
list.Add(_buf1[0]);
}
} while (!done);
byte[] a = list.ToArray();
return iso8859dash1.GetString(a, 0, a.Length);
}
internal static readonly System.Text.Encoding iso8859dash1 = System.Text.Encoding.GetEncoding("iso-8859-1");
internal static readonly System.DateTime _unixEpoch = new System.DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
private int _ReadAndValidateGzipHeader()
{
int totalBytesRead = 0;
// read the header on the first read
byte[] header = new byte[10];
int n = _stream.Read(header, 0, header.Length);
// workitem 8501: handle edge case (decompress empty stream)
if (n == 0)
return 0;
if (n != 10)
throw new ZlibException("Not a valid GZIP stream.");
if (header[0] != 0x1F || header[1] != 0x8B || header[2] != 8)
throw new ZlibException("Bad GZIP header.");
Int32 timet = BitConverter.ToInt32(header, 4);
_GzipMtime = _unixEpoch.AddSeconds(timet);
totalBytesRead += n;
if ((header[3] & 0x04) == 0x04)
{
// read and discard extra field
n = _stream.Read(header, 0, 2); // 2-byte length field
totalBytesRead += n;
Int16 extraLength = (Int16)(header[0] + header[1] * 256);
byte[] extra = new byte[extraLength];
n = _stream.Read(extra, 0, extra.Length);
if (n != extraLength)
throw new ZlibException("Unexpected end-of-file reading GZIP header.");
totalBytesRead += n;
}
if ((header[3] & 0x08) == 0x08)
_GzipFileName = ReadZeroTerminatedString();
if ((header[3] & 0x10) == 0x010)
_GzipComment = ReadZeroTerminatedString();
if ((header[3] & 0x02) == 0x02)
Read(_buf1, 0, 1); // CRC16, ignore
return totalBytesRead;
}
public override System.Int32 Read(System.Byte[] buffer, System.Int32 offset, System.Int32 count)
{
// According to MS documentation, any implementation of the IO.Stream.Read function must:
// (a) throw an exception if offset & count reference an invalid part of the buffer,
// or if count < 0, or if buffer is null
// (b) return 0 only upon EOF, or if count = 0
// (c) if not EOF, then return at least 1 byte, up to <count> bytes
if (_streamMode == StreamMode.Undefined)
{
if (!this._stream.CanRead) throw new ZlibException("The stream is not readable.");
// for the first read, set up some controls.
_streamMode = StreamMode.Reader;
// (The first reference to _z goes through the private accessor which
// may initialize it.)
z.AvailableBytesIn = 0;
if (_flavor == ZlibStreamFlavor.GZIP)
{
_gzipHeaderByteCount = _ReadAndValidateGzipHeader();
// workitem 8501: handle edge case (decompress empty stream)
if (_gzipHeaderByteCount == 0)
return 0;
}
}
if (_streamMode != StreamMode.Reader)
throw new ZlibException("Cannot Read after Writing.");
if (count == 0) return 0;
if (nomoreinput && _wantCompress) return 0; // workitem 8557
if (buffer == null) throw new ArgumentNullException("buffer");
if (count < 0) throw new ArgumentOutOfRangeException("count");
if (offset < buffer.GetLowerBound(0)) throw new ArgumentOutOfRangeException("offset");
if ((offset + count) > buffer.GetLength(0)) throw new ArgumentOutOfRangeException("count");
int rc = 0;
// set up the output of the deflate/inflate codec:
_z.OutputBuffer = buffer;
_z.NextOut = offset;
_z.AvailableBytesOut = count;
// This is necessary in case _workingBuffer has been resized. (new byte[])
// (The first reference to _workingBuffer goes through the private accessor which
// may initialize it.)
_z.InputBuffer = workingBuffer;
do
{
// need data in _workingBuffer in order to deflate/inflate. Here, we check if we have any.
if ((_z.AvailableBytesIn == 0) && (!nomoreinput))
{
// No data available, so try to Read data from the captive stream.
_z.NextIn = 0;
_z.AvailableBytesIn = _stream.Read(_workingBuffer, 0, _workingBuffer.Length);
if (_z.AvailableBytesIn == 0)
nomoreinput = true;
}
// we have data in InputBuffer; now compress or decompress as appropriate
rc = (_wantCompress)
? _z.Deflate(_flushMode)
: _z.Inflate(_flushMode);
if (nomoreinput && (rc == ZlibConstants.Z_BUF_ERROR))
return 0;
if (rc != ZlibConstants.Z_OK && rc != ZlibConstants.Z_STREAM_END)
throw new ZlibException(String.Format("{0}flating: rc={1} msg={2}", (_wantCompress ? "de" : "in"), rc, _z.Message));
if ((nomoreinput || rc == ZlibConstants.Z_STREAM_END) && (_z.AvailableBytesOut == count))
break; // nothing more to read
}
//while (_z.AvailableBytesOut == count && rc == ZlibConstants.Z_OK);
while (_z.AvailableBytesOut > 0 && !nomoreinput && rc == ZlibConstants.Z_OK);
// workitem 8557
// is there more room in output?
if (_z.AvailableBytesOut > 0)
{
if (rc == ZlibConstants.Z_OK && _z.AvailableBytesIn == 0)
{
// deferred
}
// are we completely done reading?
if (nomoreinput)
{
// and in compression?
if (_wantCompress)
{
// no more input data available; therefore we flush to
// try to complete the read
rc = _z.Deflate(FlushType.Finish);
if (rc != ZlibConstants.Z_OK && rc != ZlibConstants.Z_STREAM_END)
throw new ZlibException(String.Format("Deflating: rc={0} msg={1}", rc, _z.Message));
}
}
}
rc = (count - _z.AvailableBytesOut);
// calculate CRC after reading
if (crc != null)
crc.SlurpBlock(buffer, offset, rc);
return rc;
}
public override System.Boolean CanRead
{
get { return this._stream.CanRead; }
}
public override System.Boolean CanSeek
{
get { return this._stream.CanSeek; }
}
public override System.Boolean CanWrite
{
get { return this._stream.CanWrite; }
}
public override System.Int64 Length
{
get { return _stream.Length; }
}
public override long Position
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
public enum StreamMode
{
Writer,
Reader,
Undefined,
}
}
}

View File

@@ -1,718 +0,0 @@
// ZlibCodec.cs
// ------------------------------------------------------------------
//
// Copyright (c) 2009 Dino Chiesa and Microsoft Corporation.
// All rights reserved.
//
// This code module is part of DotNetZip, a zipfile class library.
//
// ------------------------------------------------------------------
//
// This code is licensed under the Microsoft Public License.
// See the file License.txt for the license details.
// More info on: http://dotnetzip.codeplex.com
//
// ------------------------------------------------------------------
//
// last saved (in emacs):
// Time-stamp: <2009-November-03 15:40:51>
//
// ------------------------------------------------------------------
//
// This module defines a Codec for ZLIB compression and
// decompression. This code extends code that was based the jzlib
// implementation of zlib, but this code is completely novel. The codec
// class is new, and encapsulates some behaviors that are new, and some
// that were present in other classes in the jzlib code base. In
// keeping with the license for jzlib, the copyright to the jzlib code
// is included below.
//
// ------------------------------------------------------------------
//
// Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in
// the documentation and/or other materials provided with the distribution.
//
// 3. The names of the authors may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
// INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// -----------------------------------------------------------------------
//
// This program is based on zlib-1.1.3; credit to authors
// Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
// and contributors of zlib.
//
// -----------------------------------------------------------------------
using System;
using System.Runtime.InteropServices;
using Interop = System.Runtime.InteropServices;
namespace Compress.ZipFile.ZLib
{
/// <summary>
/// Encoder and Decoder for ZLIB and DEFLATE (IETF RFC1950 and RFC1951).
/// </summary>
///
/// <remarks>
/// This class compresses and decompresses data according to the Deflate algorithm
/// and optionally, the ZLIB format, as documented in <see
/// href="http://www.ietf.org/rfc/rfc1950.txt">RFC 1950 - ZLIB</see> and <see
/// href="http://www.ietf.org/rfc/rfc1951.txt">RFC 1951 - DEFLATE</see>.
/// </remarks>
[Guid("ebc25cf6-9120-4283-b972-0e5520d0000D")]
[Interop.ComVisible(true)]
#if !NETCF
[Interop.ClassInterface(Interop.ClassInterfaceType.AutoDispatch)]
#endif
sealed public class ZlibCodec
{
/// <summary>
/// The buffer from which data is taken.
/// </summary>
public byte[] InputBuffer;
/// <summary>
/// An index into the InputBuffer array, indicating where to start reading.
/// </summary>
public int NextIn;
/// <summary>
/// The number of bytes available in the InputBuffer, starting at NextIn.
/// </summary>
/// <remarks>
/// Generally you should set this to InputBuffer.Length before the first Inflate() or Deflate() call.
/// The class will update this number as calls to Inflate/Deflate are made.
/// </remarks>
public int AvailableBytesIn;
/// <summary>
/// Total number of bytes read so far, through all calls to Inflate()/Deflate().
/// </summary>
public long TotalBytesIn;
/// <summary>
/// Buffer to store output data.
/// </summary>
public byte[] OutputBuffer;
/// <summary>
/// An index into the OutputBuffer array, indicating where to start writing.
/// </summary>
public int NextOut;
/// <summary>
/// The number of bytes available in the OutputBuffer, starting at NextOut.
/// </summary>
/// <remarks>
/// Generally you should set this to OutputBuffer.Length before the first Inflate() or Deflate() call.
/// The class will update this number as calls to Inflate/Deflate are made.
/// </remarks>
public int AvailableBytesOut;
/// <summary>
/// Total number of bytes written to the output so far, through all calls to Inflate()/Deflate().
/// </summary>
public long TotalBytesOut;
/// <summary>
/// used for diagnostics, when something goes wrong!
/// </summary>
public System.String Message;
internal DeflateManager dstate;
internal InflateManager istate;
internal uint _Adler32;
/// <summary>
/// The compression level to use in this codec. Useful only in compression mode.
/// </summary>
public CompressionLevel CompressLevel = CompressionLevel.Default;
/// <summary>
/// The number of Window Bits to use.
/// </summary>
/// <remarks>
/// This gauges the size of the sliding window, and hence the
/// compression effectiveness as well as memory consumption. It's best to just leave this
/// setting alone if you don't know what it is. The maximum value is 15 bits, which implies
/// a 32k window.
/// </remarks>
public int WindowBits = ZlibConstants.WindowBitsDefault;
/// <summary>
/// The compression strategy to use.
/// </summary>
/// <remarks>
/// This is only effective in compression. The theory offered by ZLIB is that different
/// strategies could potentially produce significant differences in compression behavior
/// for different data sets. Unfortunately I don't have any good recommendations for how
/// to set it differently. When I tested changing the strategy I got minimally different
/// compression performance. It's best to leave this property alone if you don't have a
/// good feel for it. Or, you may want to produce a test harness that runs through the
/// different strategy options and evaluates them on different file types. If you do that,
/// let me know your results.
/// </remarks>
public CompressionStrategy Strategy = CompressionStrategy.Default;
/// <summary>
/// The Adler32 checksum on the data transferred through the codec so far. You probably don't need to look at this.
/// </summary>
public int Adler32 { get { return (int)_Adler32; } }
/// <summary>
/// Create a ZlibCodec.
/// </summary>
/// <remarks>
/// If you use this default constructor, you will later have to explicitly call
/// InitializeInflate() or InitializeDeflate() before using the ZlibCodec to compress
/// or decompress.
/// </remarks>
public ZlibCodec() { }
/// <summary>
/// Create a ZlibCodec that either compresses or decompresses.
/// </summary>
/// <param name="mode">
/// Indicates whether the codec should compress (deflate) or decompress (inflate).
/// </param>
public ZlibCodec(CompressionMode mode)
{
if (mode == CompressionMode.Compress)
{
int rc = InitializeDeflate();
if (rc != ZlibConstants.Z_OK) throw new ZlibException("Cannot initialize for deflate.");
}
else if (mode == CompressionMode.Decompress)
{
int rc = InitializeInflate();
if (rc != ZlibConstants.Z_OK) throw new ZlibException("Cannot initialize for inflate.");
}
else throw new ZlibException("Invalid ZlibStreamFlavor.");
}
/// <summary>
/// Initialize the inflation state.
/// </summary>
/// <remarks>
/// It is not necessary to call this before using the ZlibCodec to inflate data;
/// It is implicitly called when you call the constructor.
/// </remarks>
/// <returns>Z_OK if everything goes well.</returns>
public int InitializeInflate()
{
return InitializeInflate(this.WindowBits);
}
/// <summary>
/// Initialize the inflation state with an explicit flag to
/// govern the handling of RFC1950 header bytes.
/// </summary>
///
/// <remarks>
/// By default, the ZLIB header defined in <see
/// href="http://www.ietf.org/rfc/rfc1950.txt">RFC 1950</see> is expected. If
/// you want to read a zlib stream you should specify true for
/// expectRfc1950Header. If you have a deflate stream, you will want to specify
/// false. It is only necessary to invoke this initializer explicitly if you
/// want to specify false.
/// </remarks>
///
/// <param name="expectRfc1950Header">whether to expect an RFC1950 header byte
/// pair when reading the stream of data to be inflated.</param>
///
/// <returns>Z_OK if everything goes well.</returns>
public int InitializeInflate(bool expectRfc1950Header)
{
return InitializeInflate(this.WindowBits, expectRfc1950Header);
}
/// <summary>
/// Initialize the ZlibCodec for inflation, with the specified number of window bits.
/// </summary>
/// <param name="windowBits">The number of window bits to use. If you need to ask what that is,
/// then you shouldn't be calling this initializer.</param>
/// <returns>Z_OK if all goes well.</returns>
public int InitializeInflate(int windowBits)
{
this.WindowBits = windowBits;
return InitializeInflate(windowBits, true);
}
/// <summary>
/// Initialize the inflation state with an explicit flag to govern the handling of
/// RFC1950 header bytes.
/// </summary>
///
/// <remarks>
/// If you want to read a zlib stream you should specify true for
/// expectRfc1950Header. In this case, the library will expect to find a ZLIB
/// header, as defined in <see href="http://www.ietf.org/rfc/rfc1950.txt">RFC
/// 1950</see>, in the compressed stream. If you will be reading a DEFLATE or
/// GZIP stream, which does not have such a header, you will want to specify
/// false.
/// </remarks>
///
/// <param name="expectRfc1950Header">whether to expect an RFC1950 header byte pair when reading
/// the stream of data to be inflated.</param>
/// <param name="windowBits">The number of window bits to use. If you need to ask what that is,
/// then you shouldn't be calling this initializer.</param>
/// <returns>Z_OK if everything goes well.</returns>
public int InitializeInflate(int windowBits, bool expectRfc1950Header)
{
this.WindowBits = windowBits;
if (dstate != null) throw new ZlibException("You may not call InitializeInflate() after calling InitializeDeflate().");
istate = new InflateManager(expectRfc1950Header);
return istate.Initialize(this, windowBits);
}
/// <summary>
/// Inflate the data in the InputBuffer, placing the result in the OutputBuffer.
/// </summary>
/// <remarks>
/// You must have set InputBuffer and OutputBuffer, NextIn and NextOut, and AvailableBytesIn and
/// AvailableBytesOut before calling this method.
/// </remarks>
/// <example>
/// <code>
/// private void InflateBuffer()
/// {
/// int bufferSize = 1024;
/// byte[] buffer = new byte[bufferSize];
/// ZlibCodec decompressor = new ZlibCodec();
///
/// Console.WriteLine("\n============================================");
/// Console.WriteLine("Size of Buffer to Inflate: {0} bytes.", CompressedBytes.Length);
/// MemoryStream ms = new MemoryStream(DecompressedBytes);
///
/// int rc = decompressor.InitializeInflate();
///
/// decompressor.InputBuffer = CompressedBytes;
/// decompressor.NextIn = 0;
/// decompressor.AvailableBytesIn = CompressedBytes.Length;
///
/// decompressor.OutputBuffer = buffer;
///
/// // pass 1: inflate
/// do
/// {
/// decompressor.NextOut = 0;
/// decompressor.AvailableBytesOut = buffer.Length;
/// rc = decompressor.Inflate(FlushType.None);
///
/// if (rc != ZlibConstants.Z_OK &amp;&amp; rc != ZlibConstants.Z_STREAM_END)
/// throw new Exception("inflating: " + decompressor.Message);
///
/// ms.Write(decompressor.OutputBuffer, 0, buffer.Length - decompressor.AvailableBytesOut);
/// }
/// while (decompressor.AvailableBytesIn &gt; 0 || decompressor.AvailableBytesOut == 0);
///
/// // pass 2: finish and flush
/// do
/// {
/// decompressor.NextOut = 0;
/// decompressor.AvailableBytesOut = buffer.Length;
/// rc = decompressor.Inflate(FlushType.Finish);
///
/// if (rc != ZlibConstants.Z_STREAM_END &amp;&amp; rc != ZlibConstants.Z_OK)
/// throw new Exception("inflating: " + decompressor.Message);
///
/// if (buffer.Length - decompressor.AvailableBytesOut &gt; 0)
/// ms.Write(buffer, 0, buffer.Length - decompressor.AvailableBytesOut);
/// }
/// while (decompressor.AvailableBytesIn &gt; 0 || decompressor.AvailableBytesOut == 0);
///
/// decompressor.EndInflate();
/// }
///
/// </code>
/// </example>
/// <param name="flush">The flush to use when inflating.</param>
/// <returns>Z_OK if everything goes well.</returns>
public int Inflate(FlushType flush)
{
if (istate == null)
throw new ZlibException("No Inflate State!");
return istate.Inflate(flush);
}
/// <summary>
/// Ends an inflation session.
/// </summary>
/// <remarks>
/// Call this after successively calling Inflate(). This will cause all buffers to be flushed.
/// After calling this you cannot call Inflate() without a intervening call to one of the
/// InitializeInflate() overloads.
/// </remarks>
/// <returns>Z_OK if everything goes well.</returns>
public int EndInflate()
{
if (istate == null)
throw new ZlibException("No Inflate State!");
int ret = istate.End();
istate = null;
return ret;
}
/// <summary>
/// I don't know what this does!
/// </summary>
/// <returns>Z_OK if everything goes well.</returns>
public int SyncInflate()
{
if (istate == null)
throw new ZlibException("No Inflate State!");
return istate.Sync();
}
/// <summary>
/// Initialize the ZlibCodec for deflation operation.
/// </summary>
/// <remarks>
/// The codec will use the MAX window bits and the default level of compression.
/// </remarks>
/// <example>
/// <code>
/// int bufferSize = 40000;
/// byte[] CompressedBytes = new byte[bufferSize];
/// byte[] DecompressedBytes = new byte[bufferSize];
///
/// ZlibCodec compressor = new ZlibCodec();
///
/// compressor.InitializeDeflate(CompressionLevel.Default);
///
/// compressor.InputBuffer = System.Text.ASCIIEncoding.ASCII.GetBytes(TextToCompress);
/// compressor.NextIn = 0;
/// compressor.AvailableBytesIn = compressor.InputBuffer.Length;
///
/// compressor.OutputBuffer = CompressedBytes;
/// compressor.NextOut = 0;
/// compressor.AvailableBytesOut = CompressedBytes.Length;
///
/// while (compressor.TotalBytesIn != TextToCompress.Length &amp;&amp; compressor.TotalBytesOut &lt; bufferSize)
/// {
/// compressor.Deflate(FlushType.None);
/// }
///
/// while (true)
/// {
/// int rc= compressor.Deflate(FlushType.Finish);
/// if (rc == ZlibConstants.Z_STREAM_END) break;
/// }
///
/// compressor.EndDeflate();
///
/// </code>
/// </example>
/// <returns>Z_OK if all goes well. You generally don't need to check the return code.</returns>
public int InitializeDeflate()
{
return _InternalInitializeDeflate(true);
}
/// <summary>
/// Initialize the ZlibCodec for deflation operation, using the specified CompressionLevel.
/// </summary>
/// <remarks>
/// The codec will use the maximum window bits (15) and the specified
/// CompressionLevel. It will emit a ZLIB stream as it compresses.
/// </remarks>
/// <param name="level">The compression level for the codec.</param>
/// <returns>Z_OK if all goes well.</returns>
public int InitializeDeflate(CompressionLevel level)
{
this.CompressLevel = level;
return _InternalInitializeDeflate(true);
}
/// <summary>
/// Initialize the ZlibCodec for deflation operation, using the specified CompressionLevel,
/// and the explicit flag governing whether to emit an RFC1950 header byte pair.
/// </summary>
/// <remarks>
/// The codec will use the maximum window bits (15) and the specified CompressionLevel.
/// If you want to generate a zlib stream, you should specify true for
/// wantRfc1950Header. In this case, the library will emit a ZLIB
/// header, as defined in <see href="http://www.ietf.org/rfc/rfc1950.txt">RFC
/// 1950</see>, in the compressed stream.
/// </remarks>
/// <param name="level">The compression level for the codec.</param>
/// <param name="wantRfc1950Header">whether to emit an initial RFC1950 byte pair in the compressed stream.</param>
/// <returns>Z_OK if all goes well.</returns>
public int InitializeDeflate(CompressionLevel level, bool wantRfc1950Header)
{
this.CompressLevel = level;
return _InternalInitializeDeflate(wantRfc1950Header);
}
/// <summary>
/// Initialize the ZlibCodec for deflation operation, using the specified CompressionLevel,
/// and the specified number of window bits.
/// </summary>
/// <remarks>
/// The codec will use the specified number of window bits and the specified CompressionLevel.
/// </remarks>
/// <param name="level">The compression level for the codec.</param>
/// <param name="bits">the number of window bits to use. If you don't know what this means, don't use this method.</param>
/// <returns>Z_OK if all goes well.</returns>
public int InitializeDeflate(CompressionLevel level, int bits)
{
this.CompressLevel = level;
this.WindowBits = bits;
return _InternalInitializeDeflate(true);
}
/// <summary>
/// Initialize the ZlibCodec for deflation operation, using the specified
/// CompressionLevel, the specified number of window bits, and the explicit flag
/// governing whether to emit an RFC1950 header byte pair.
/// </summary>
///
/// <param name="level">The compression level for the codec.</param>
/// <param name="wantRfc1950Header">whether to emit an initial RFC1950 byte pair in the compressed stream.</param>
/// <param name="bits">the number of window bits to use. If you don't know what this means, don't use this method.</param>
/// <returns>Z_OK if all goes well.</returns>
public int InitializeDeflate(CompressionLevel level, int bits, bool wantRfc1950Header)
{
this.CompressLevel = level;
this.WindowBits = bits;
return _InternalInitializeDeflate(wantRfc1950Header);
}
private int _InternalInitializeDeflate(bool wantRfc1950Header)
{
if (istate != null) throw new ZlibException("You may not call InitializeDeflate() after calling InitializeInflate().");
dstate = new DeflateManager();
dstate.WantRfc1950HeaderBytes = wantRfc1950Header;
return dstate.Initialize(this, this.CompressLevel, this.WindowBits, this.Strategy);
}
/// <summary>
/// Deflate one batch of data.
/// </summary>
/// <remarks>
/// You must have set InputBuffer and OutputBuffer before calling this method.
/// </remarks>
/// <example>
/// <code>
/// private void DeflateBuffer(CompressionLevel level)
/// {
/// int bufferSize = 1024;
/// byte[] buffer = new byte[bufferSize];
/// ZlibCodec compressor = new ZlibCodec();
///
/// Console.WriteLine("\n============================================");
/// Console.WriteLine("Size of Buffer to Deflate: {0} bytes.", UncompressedBytes.Length);
/// MemoryStream ms = new MemoryStream();
///
/// int rc = compressor.InitializeDeflate(level);
///
/// compressor.InputBuffer = UncompressedBytes;
/// compressor.NextIn = 0;
/// compressor.AvailableBytesIn = UncompressedBytes.Length;
///
/// compressor.OutputBuffer = buffer;
///
/// // pass 1: deflate
/// do
/// {
/// compressor.NextOut = 0;
/// compressor.AvailableBytesOut = buffer.Length;
/// rc = compressor.Deflate(FlushType.None);
///
/// if (rc != ZlibConstants.Z_OK &amp;&amp; rc != ZlibConstants.Z_STREAM_END)
/// throw new Exception("deflating: " + compressor.Message);
///
/// ms.Write(compressor.OutputBuffer, 0, buffer.Length - compressor.AvailableBytesOut);
/// }
/// while (compressor.AvailableBytesIn &gt; 0 || compressor.AvailableBytesOut == 0);
///
/// // pass 2: finish and flush
/// do
/// {
/// compressor.NextOut = 0;
/// compressor.AvailableBytesOut = buffer.Length;
/// rc = compressor.Deflate(FlushType.Finish);
///
/// if (rc != ZlibConstants.Z_STREAM_END &amp;&amp; rc != ZlibConstants.Z_OK)
/// throw new Exception("deflating: " + compressor.Message);
///
/// if (buffer.Length - compressor.AvailableBytesOut &gt; 0)
/// ms.Write(buffer, 0, buffer.Length - compressor.AvailableBytesOut);
/// }
/// while (compressor.AvailableBytesIn &gt; 0 || compressor.AvailableBytesOut == 0);
///
/// compressor.EndDeflate();
///
/// ms.Seek(0, SeekOrigin.Begin);
/// CompressedBytes = new byte[compressor.TotalBytesOut];
/// ms.Read(CompressedBytes, 0, CompressedBytes.Length);
/// }
/// </code>
/// </example>
/// <param name="flush">whether to flush all data as you deflate. Generally you will want to
/// use Z_NO_FLUSH here, in a series of calls to Deflate(), and then call EndDeflate() to
/// flush everything.
/// </param>
/// <returns>Z_OK if all goes well.</returns>
public int Deflate(FlushType flush)
{
if (dstate == null)
throw new ZlibException("No Deflate State!");
return dstate.Deflate(flush);
}
/// <summary>
/// End a deflation session.
/// </summary>
/// <remarks>
/// Call this after making a series of one or more calls to Deflate(). All buffers are flushed.
/// </remarks>
/// <returns>Z_OK if all goes well.</returns>
public int EndDeflate()
{
if (dstate == null)
throw new ZlibException("No Deflate State!");
// TODO: dinoch Tue, 03 Nov 2009 15:39 (test this)
//int ret = dstate.End();
dstate = null;
return ZlibConstants.Z_OK; //ret;
}
/// <summary>
/// Reset a codec for another deflation session.
/// </summary>
/// <remarks>
/// Call this to reset the deflation state. For example if a thread is deflating
/// non-consecutive blocks, you can call Reset() after the Deflate(Sync) of the first
/// block and before the next Deflate(None) of the second block.
/// </remarks>
/// <returns>Z_OK if all goes well.</returns>
public void ResetDeflate()
{
if (dstate == null)
throw new ZlibException("No Deflate State!");
dstate.Reset();
}
/// <summary>
/// Set the CompressionStrategy and CompressionLevel for a deflation session.
/// </summary>
/// <param name="level">the level of compression to use.</param>
/// <param name="strategy">the strategy to use for compression.</param>
/// <returns>Z_OK if all goes well.</returns>
public int SetDeflateParams(CompressionLevel level, CompressionStrategy strategy)
{
if (dstate == null)
throw new ZlibException("No Deflate State!");
return dstate.SetParams(level, strategy);
}
/// <summary>
/// Set the dictionary to be used for either Inflation or Deflation.
/// </summary>
/// <param name="dictionary">The dictionary bytes to use.</param>
/// <returns>Z_OK if all goes well.</returns>
public int SetDictionary(byte[] dictionary)
{
if (istate != null)
return istate.SetDictionary(dictionary);
if (dstate != null)
return dstate.SetDictionary(dictionary);
throw new ZlibException("No Inflate or Deflate state!");
}
// Flush as much pending output as possible. All deflate() output goes
// through this function so some applications may wish to modify it
// to avoid allocating a large strm->next_out buffer and copying into it.
// (See also read_buf()).
internal void flush_pending()
{
int len = dstate.pendingCount;
if (len > AvailableBytesOut)
len = AvailableBytesOut;
if (len == 0)
return;
if (dstate.pending.Length <= dstate.nextPending ||
OutputBuffer.Length <= NextOut ||
dstate.pending.Length < (dstate.nextPending + len) ||
OutputBuffer.Length < (NextOut + len))
{
throw new ZlibException(String.Format("Invalid State. (pending.Length={0}, pendingCount={1})",
dstate.pending.Length, dstate.pendingCount));
}
Array.Copy(dstate.pending, dstate.nextPending, OutputBuffer, NextOut, len);
NextOut += len;
dstate.nextPending += len;
TotalBytesOut += len;
AvailableBytesOut -= len;
dstate.pendingCount -= len;
if (dstate.pendingCount == 0)
{
dstate.nextPending = 0;
}
}
// Read a new buffer from the current input stream, update the adler32
// and total number of bytes read. All deflate() input goes through
// this function so some applications may wish to modify it to avoid
// allocating a large strm->next_in buffer and copying from it.
// (See also flush_pending()).
internal int read_buf(byte[] buf, int start, int size)
{
int len = AvailableBytesIn;
if (len > size)
len = size;
if (len == 0)
return 0;
AvailableBytesIn -= len;
if (dstate.WantRfc1950HeaderBytes)
{
_Adler32 = Adler.Adler32(_Adler32, InputBuffer, NextIn, len);
}
Array.Copy(InputBuffer, NextIn, buf, start, len);
NextIn += len;
TotalBytesIn += len;
return len;
}
}
}

View File

@@ -1,125 +0,0 @@
// ZlibConstants.cs
// ------------------------------------------------------------------
//
// Copyright (c) 2009 Dino Chiesa and Microsoft Corporation.
// All rights reserved.
//
// This code module is part of DotNetZip, a zipfile class library.
//
// ------------------------------------------------------------------
//
// This code is licensed under the Microsoft Public License.
// See the file License.txt for the license details.
// More info on: http://dotnetzip.codeplex.com
//
// ------------------------------------------------------------------
//
// last saved (in emacs):
// Time-stamp: <2009-November-03 18:50:19>
//
// ------------------------------------------------------------------
//
// This module defines constants used by the zlib class library. This
// code is derived from the jzlib implementation of zlib, but
// significantly modified. In keeping with the license for jzlib, the
// copyright to that code is included here.
//
// ------------------------------------------------------------------
//
// Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in
// the documentation and/or other materials provided with the distribution.
//
// 3. The names of the authors may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
// INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// -----------------------------------------------------------------------
//
// This program is based on zlib-1.1.3; credit to authors
// Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
// and contributors of zlib.
//
// -----------------------------------------------------------------------
namespace Compress.ZipFile.ZLib
{
/// <summary>
/// A bunch of constants used in the Zlib interface.
/// </summary>
public static class ZlibConstants
{
/// <summary>
/// The maximum number of window bits for the Deflate algorithm.
/// </summary>
public const int WindowBitsMax = 15; // 32K LZ77 window
/// <summary>
/// The default number of window bits for the Deflate algorithm.
/// </summary>
public const int WindowBitsDefault = WindowBitsMax;
/// <summary>
/// indicates everything is A-OK
/// </summary>
public const int Z_OK = 0;
/// <summary>
/// Indicates that the last operation reached the end of the stream.
/// </summary>
public const int Z_STREAM_END = 1;
/// <summary>
/// The operation ended in need of a dictionary.
/// </summary>
public const int Z_NEED_DICT = 2;
/// <summary>
/// There was an error with the stream - not enough data, not open and readable, etc.
/// </summary>
public const int Z_STREAM_ERROR = -2;
/// <summary>
/// There was an error with the data - not enough data, bad data, etc.
/// </summary>
public const int Z_DATA_ERROR = -3;
/// <summary>
/// There was an error with the working buffer.
/// </summary>
public const int Z_BUF_ERROR = -5;
/// <summary>
/// The size of the working buffer used in the ZlibCodec class. Defaults to 8192 bytes.
/// </summary>
#if NETCF
public const int WorkingBufferSizeDefault = 8192;
#else
public const int WorkingBufferSizeDefault = 16384;
#endif
/// <summary>
/// The minimum size of the working buffer used in the ZlibCodec class. Currently it is 128 bytes.
/// </summary>
public const int WorkingBufferSizeMin = 1024;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,458 +0,0 @@
using System;
using System.IO;
using System.Text;
using Compress.ZipFile.ZLib;
using Directory = RVIO.Directory;
using FileInfo = RVIO.FileInfo;
using FileStream = RVIO.FileStream;
using Path = RVIO.Path;
namespace Compress.gZip
{
public class gZip : ICompress
{
private FileInfo _zipFileInfo;
private Stream _zipFs;
private Stream _compressionStream;
public byte[] CRC { get; private set; }
public ulong UnCompressedSize { get; private set; }
public ulong CompressedSize { get; private set; }
private long headerStartPos;
private long dataStartPos;
public int LocalFilesCount()
{
return 1;
}
public string Filename(int i)
{
return Path.GetFileName(ZipFilename);
}
public ulong? LocalHeader(int i)
{
return 0;
}
public ulong UncompressedSize(int i)
{
return UnCompressedSize;
}
public byte[] CRC32(int i)
{
return CRC;
}
public bool IsDirectory(int i)
{
return false;
}
public ZipOpenType ZipOpen { get; private set; }
public ZipReturn ZipFileOpen(string newFilename, long timestamp = -1, bool readHeaders = true)
{
ZipFileClose();
ZipStatus = ZipStatus.None;
try
{
if (!RVIO.File.Exists(newFilename))
{
ZipFileClose();
return ZipReturn.ZipErrorFileNotFound;
}
_zipFileInfo = new FileInfo(newFilename);
if (timestamp != -1 && _zipFileInfo.LastWriteTime != timestamp)
{
ZipFileClose();
return ZipReturn.ZipErrorTimeStamp;
}
int errorCode = FileStream.OpenFileRead(newFilename, out _zipFs);
if (errorCode != 0)
{
ZipFileClose();
if (errorCode == 32)
{
return ZipReturn.ZipFileLocked;
}
return ZipReturn.ZipErrorOpeningFile;
}
}
catch (PathTooLongException)
{
ZipFileClose();
return ZipReturn.ZipFileNameToLong;
}
catch (IOException)
{
ZipFileClose();
return ZipReturn.ZipErrorOpeningFile;
}
ZipOpen = ZipOpenType.OpenRead;
if (!readHeaders)
{
return ZipReturn.ZipGood;
}
return ZipFileReadHeaders();
}
public ZipReturn ZipFileOpen(Stream inStream)
{
ZipFileClose();
ZipStatus = ZipStatus.None;
_zipFileInfo = null;
_zipFs = inStream;
ZipOpen = ZipOpenType.OpenRead;
return ZipFileReadHeaders();
}
private ZipReturn ZipFileReadHeaders()
{
using (BinaryReader zipBr = new BinaryReader(_zipFs, Encoding.UTF8, true))
{
byte ID1 = zipBr.ReadByte();
byte ID2 = zipBr.ReadByte();
if ((ID1 != 0x1f) || (ID2 != 0x8b))
{
_zipFs.Close();
return ZipReturn.ZipSignatureError;
}
byte CM = zipBr.ReadByte();
if (CM != 8)
{
_zipFs.Close();
return ZipReturn.ZipUnsupportedCompression;
}
byte FLG = zipBr.ReadByte();
uint MTime = zipBr.ReadUInt32();
byte XFL = zipBr.ReadByte();
byte OS = zipBr.ReadByte();
ExtraData = null;
//if FLG.FEXTRA set
if ((FLG & 0x4) == 0x4)
{
int XLen = zipBr.ReadInt16();
ExtraData = zipBr.ReadBytes(XLen);
switch (XLen)
{
case 12:
CRC = new byte[4];
Array.Copy(ExtraData, 0, CRC, 0, 4);
UnCompressedSize = BitConverter.ToUInt64(ExtraData, 4);
break;
case 28:
CRC = new byte[4];
Array.Copy(ExtraData, 16, CRC, 0, 4);
UnCompressedSize = BitConverter.ToUInt64(ExtraData, 20);
break;
case 77:
CRC = new byte[4];
Array.Copy(ExtraData, 16, CRC, 0, 4);
UnCompressedSize = BitConverter.ToUInt64(ExtraData, 20);
break;
}
}
//if FLG.FNAME set
if ((FLG & 0x8) == 0x8)
{
int XLen = zipBr.ReadInt16();
byte[] bytes = zipBr.ReadBytes(XLen);
}
//if FLG.FComment set
if ((FLG & 0x10) == 0x10)
{
int XLen = zipBr.ReadInt16();
byte[] bytes = zipBr.ReadBytes(XLen);
}
//if FLG.FHCRC set
if ((FLG & 0x2) == 0x2)
{
uint crc16 = zipBr.ReadUInt16();
}
CompressedSize = (ulong)(_zipFs.Length - _zipFs.Position) - 8;
dataStartPos = _zipFs.Position;
_zipFs.Position = _zipFs.Length - 8;
byte[] gzcrc = zipBr.ReadBytes(4);
uint gzLength = zipBr.ReadUInt32();
if (CRC != null)
{
for (int i = 0; i < 4; i++)
{
if (gzcrc[3 - i] == CRC[i])
{
continue;
}
_zipFs.Close();
return ZipReturn.ZipDecodeError;
}
}
else
{
CRC = new[] { gzcrc[3], gzcrc[2], gzcrc[1], gzcrc[0] };
}
if (UnCompressedSize != 0)
{
if (gzLength != (UnCompressedSize & 0xffffffff))
{
_zipFs.Close();
return ZipReturn.ZipDecodeError;
}
}
return ZipReturn.ZipGood;
}
}
public void ZipFileClose()
{
if (ZipOpen == ZipOpenType.Closed)
{
return;
}
if (ZipOpen == ZipOpenType.OpenRead)
{
if (_zipFs != null)
{
_zipFs.Close();
_zipFs.Dispose();
}
ZipOpen = ZipOpenType.Closed;
return;
}
}
public ZipReturn ZipFileOpenReadStream(int index, out Stream stream, out ulong streamSize)
{
ZipFileCloseReadStream();
_zipFs.Position = dataStartPos;
_compressionStream = new ZlibBaseStream(_zipFs, CompressionMode.Decompress, CompressionLevel.Default, ZlibStreamFlavor.DEFLATE, true);
stream = _compressionStream;
streamSize = UnCompressedSize;
return ZipReturn.ZipGood;
}
public bool hasAltFileHeader;
public byte[] ExtraData;
public ZipReturn ZipFileOpenWriteStream(bool raw, bool trrntzip, string filename, ulong unCompressedSize, ushort compressionMethod, uint? datetime, out Stream stream)
{
using (BinaryWriter zipBw = new BinaryWriter(_zipFs, Encoding.UTF8, true))
{
UnCompressedSize = unCompressedSize;
zipBw.Write((byte)0x1f); // ID1 = 0x1f
zipBw.Write((byte)0x8b); // ID2 = 0x8b
zipBw.Write((byte)0x08); // CM = 0x08
zipBw.Write((byte)0x04); // FLG = 0x04
zipBw.Write((uint)0); // MTime = 0
zipBw.Write((byte)0x00); // XFL = 0x00
zipBw.Write((byte)0xff); // OS = 0x00
if (ExtraData == null)
{
zipBw.Write((short)12);
headerStartPos = zipBw.BaseStream.Position;
zipBw.Write(new byte[12]);
}
else
{
zipBw.Write((short)ExtraData.Length); // XLEN 16+4+8+1+16+20+4+8
headerStartPos = zipBw.BaseStream.Position;
zipBw.Write(ExtraData);
}
dataStartPos = zipBw.BaseStream.Position;
stream = raw
? _zipFs
: new ZlibBaseStream(_zipFs, CompressionMode.Compress, CompressionLevel.BestCompression, ZlibStreamFlavor.DEFLATE, true);
zipBw.Flush();
zipBw.Close();
}
return ZipReturn.ZipGood;
}
public ZipReturn ZipFileCloseReadStream()
{
if (_compressionStream == null)
return ZipReturn.ZipGood;
if (_compressionStream is ZlibBaseStream dfStream)
{
dfStream.Close();
dfStream.Dispose();
}
_compressionStream = null;
return ZipReturn.ZipGood;
}
public ZipStatus ZipStatus { get; private set; }
public string ZipFilename => _zipFileInfo != null ? _zipFileInfo.FullName : string.Empty;
public long TimeStamp => _zipFileInfo?.LastWriteTime ?? 0;
public void ZipFileAddZeroLengthFile()
{
throw new NotImplementedException();
}
public ZipReturn ZipFileCreate(string newFilename)
{
if (ZipOpen != ZipOpenType.Closed)
{
return ZipReturn.ZipFileAlreadyOpen;
}
CreateDirForFile(newFilename);
_zipFileInfo = new FileInfo(newFilename);
int errorCode = FileStream.OpenFileWrite(newFilename, out _zipFs);
if (errorCode != 0)
{
ZipFileClose();
return ZipReturn.ZipErrorOpeningFile;
}
ZipOpen = ZipOpenType.OpenWrite;
return ZipReturn.ZipGood;
}
public ZipReturn ZipFileCloseWriteStream(byte[] crc32)
{
using (BinaryWriter zipBw = new BinaryWriter(_zipFs, Encoding.UTF8, true))
{
CompressedSize = (ulong)(zipBw.BaseStream.Position - dataStartPos);
zipBw.Write(CRC[3]);
zipBw.Write(CRC[2]);
zipBw.Write(CRC[1]);
zipBw.Write(CRC[0]);
zipBw.Write((uint)UnCompressedSize);
long endpos = _zipFs.Position;
_zipFs.Position = headerStartPos;
if (ExtraData == null)
{
zipBw.Write(CRC); // 4 bytes
zipBw.Write(UnCompressedSize); // 8 bytes
}
else
{
zipBw.Write(ExtraData);
}
_zipFs.Position = endpos;
zipBw.Flush();
zipBw.Close();
}
_zipFs.Close();
return ZipReturn.ZipGood;
}
public ZipReturn ZipFileRollBack()
{
_zipFs.Position = dataStartPos;
return ZipReturn.ZipGood;
}
public void ZipFileCloseFailed()
{
if (ZipOpen == ZipOpenType.Closed)
{
return;
}
if (ZipOpen == ZipOpenType.OpenRead)
{
if (_zipFs != null)
{
_zipFs.Close();
_zipFs.Dispose();
}
ZipOpen = ZipOpenType.Closed;
return;
}
_zipFs.Flush();
_zipFs.Close();
_zipFs.Dispose();
RVIO.File.Delete(_zipFileInfo.FullName);
_zipFileInfo = null;
ZipOpen = ZipOpenType.Closed;
}
private static void CreateDirForFile(string sFilename)
{
string strTemp = Path.GetDirectoryName(sFilename);
if (string.IsNullOrEmpty(strTemp))
{
return;
}
if (Directory.Exists(strTemp))
{
return;
}
while (strTemp.Length > 0 && !Directory.Exists(strTemp))
{
int pos = strTemp.LastIndexOf(Path.DirectorySeparatorChar);
if (pos < 0)
{
pos = 0;
}
strTemp = strTemp.Substring(0, pos);
}
while (sFilename.IndexOf(Path.DirectorySeparatorChar, strTemp.Length + 1) > 0)
{
strTemp = sFilename.Substring(0, sFilename.IndexOf(Path.DirectorySeparatorChar, strTemp.Length + 1));
Directory.CreateDirectory(strTemp);
}
}
}
}

View File

@@ -1,96 +0,0 @@
/*
*
* Links for info and original source code:
*
* https://blog.codinghorror.com/sorting-for-humans-natural-sort-order/
* http://www.codeproject.com/Articles/22517/Natural-Sort-Comparer
*
* Exact code implementation used with permission, originally by motoschifo
*
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
namespace NaturalSort
{
public class NaturalComparer : Comparer<string>, IDisposable
{
private Dictionary<string, string[]> table;
public NaturalComparer()
{
table = new Dictionary<string, string[]>();
}
public void Dispose()
{
table.Clear();
table = null;
}
public override int Compare(string x, string y)
{
if (x.ToLowerInvariant() == y.ToLowerInvariant())
{
return x.CompareTo(y);
}
if (!table.TryGetValue(x, out string[] x1))
{
//x1 = Regex.Split(x.Replace(" ", string.Empty), "([0-9]+)");
x1 = Regex.Split(x.ToLowerInvariant(), "([0-9]+)").Where(s => !string.IsNullOrWhiteSpace(s)).ToArray();
table.Add(x, x1);
}
if (!table.TryGetValue(y, out string[] y1))
{
//y1 = Regex.Split(y.Replace(" ", string.Empty), "([0-9]+)");
y1 = Regex.Split(y.ToLowerInvariant(), "([0-9]+)").Where(s => !string.IsNullOrWhiteSpace(s)).ToArray();
table.Add(y, y1);
}
for (int i = 0; i < x1.Length && i < y1.Length; i++)
{
if (x1[i] != y1[i])
{
return PartCompare(x1[i], y1[i]);
}
}
if (y1.Length > x1.Length)
{
return 1;
}
else if (x1.Length > y1.Length)
{
return -1;
}
else
{
return x.CompareTo(y);
}
}
private static int PartCompare(string left, string right)
{
if (!long.TryParse(left, out long x))
{
return NaturalComparerUtil.CompareNumeric(left, right);
}
if (!long.TryParse(right, out long y))
{
return NaturalComparerUtil.CompareNumeric(left, right);
}
// If we have an equal part, then make sure that "longer" ones are taken into account
if (x.CompareTo(y) == 0)
{
return left.Length - right.Length;
}
return x.CompareTo(y);
}
}
}

View File

@@ -1,78 +0,0 @@
using System.IO;
namespace NaturalSort
{
public static class NaturalComparerUtil
{
public static int CompareNumeric(string s1, string s2)
{
// Save the orginal strings, for later comparison
string s1orig = s1;
string s2orig = s2;
// We want to normalize the strings, so we set both to lower case
s1 = s1.ToLowerInvariant();
s2 = s2.ToLowerInvariant();
// If the strings are the same exactly, return
if (s1 == s2)
return s1orig.CompareTo(s2orig);
// If one is null, then say that's less than
if (s1 == null)
return -1;
if (s2 == null)
return 1;
// Now split into path parts after converting AltDirSeparator to DirSeparator
s1 = s1.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
s2 = s2.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
string[] s1parts = s1.Split(Path.DirectorySeparatorChar);
string[] s2parts = s2.Split(Path.DirectorySeparatorChar);
// Then compare each part in turn
for (int j = 0; j < s1parts.Length && j < s2parts.Length; j++)
{
int compared = CompareNumericPart(s1parts[j], s2parts[j]);
if (compared != 0)
return compared;
}
// If we got out here, then it looped through at least one of the strings
if (s1parts.Length > s2parts.Length)
return 1;
if (s1parts.Length < s2parts.Length)
return -1;
return s1orig.CompareTo(s2orig);
}
private static int CompareNumericPart(string s1, string s2)
{
// Otherwise, loop through until we have an answer
for (int i = 0; i < s1.Length && i < s2.Length; i++)
{
int s1c = s1[i];
int s2c = s2[i];
// If the characters are the same, continue
if (s1c == s2c)
continue;
// If they're different, check which one was larger
if (s1c > s2c)
return 1;
if (s1c < s2c)
return -1;
}
// If we got out here, then it looped through at least one of the strings
if (s1.Length > s2.Length)
return 1;
if (s1.Length < s2.Length)
return -1;
return 0;
}
}
}

View File

@@ -1,95 +0,0 @@
/*
*
* Links for info and original source code:
*
* https://blog.codinghorror.com/sorting-for-humans-natural-sort-order/
* http://www.codeproject.com/Articles/22517/Natural-Sort-Comparer
*
* Exact code implementation used with permission, originally by motoschifo
*
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace NaturalSort
{
public class NaturalReversedComparer : Comparer<string>, IDisposable
{
private Dictionary<string, string[]> table;
public NaturalReversedComparer()
{
table = new Dictionary<string, string[]>();
}
public void Dispose()
{
table.Clear();
table = null;
}
public override int Compare(string x, string y)
{
if (y.ToLowerInvariant() == x.ToLowerInvariant())
{
return y.CompareTo(x);
}
if (!table.TryGetValue(x, out string[] x1))
{
//x1 = Regex.Split(x.Replace(" ", string.Empty), "([0-9]+)");
x1 = Regex.Split(x.ToLowerInvariant(), "([0-9]+)").Where(s => !string.IsNullOrWhiteSpace(s)).ToArray();
table.Add(x, x1);
}
if (!table.TryGetValue(y, out string[] y1))
{
//y1 = Regex.Split(y.Replace(" ", string.Empty), "([0-9]+)");
y1 = Regex.Split(y.ToLowerInvariant(), "([0-9]+)").Where(s => !string.IsNullOrWhiteSpace(s)).ToArray();
table.Add(y, y1);
}
for (int i = 0; i < x1.Length && i < y1.Length; i++)
{
if (x1[i] != y1[i])
{
return PartCompare(x1[i], y1[i]);
}
}
if (y1.Length > x1.Length)
{
return 1;
}
else if (x1.Length > y1.Length)
{
return -1;
}
else
{
return y.CompareTo(x);
}
}
private static int PartCompare(string left, string right)
{
if (!long.TryParse(left, out long x))
{
return NaturalComparerUtil.CompareNumeric(right, left);
}
if (!long.TryParse(right, out long y))
{
return NaturalComparerUtil.CompareNumeric(right, left);
}
// If we have an equal part, then make sure that "longer" ones are taken into account
if (y.CompareTo(x) == 0)
{
return right.Length - left.Length;
}
return y.CompareTo(x);
}
}
}

View File

@@ -1,786 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.Win32.SafeHandles;
namespace RVIO
{
[Flags]
[ComVisible(true)]
[Serializable]
public enum FileAttributes
{
ReadOnly = 1,
Hidden = 2,
System = 4,
Directory = 16,
Archive = 32,
Device = 64,
Normal = 128,
Temporary = 256,
SparseFile = 512,
ReparsePoint = 1024,
Compressed = 2048,
Offline = 4096,
NotContentIndexed = 8192,
Encrypted = 16384,
}
public static class Error
{
public static int GetLastError()
{
return Marshal.GetLastWin32Error();
}
}
public static class unix
{
public static bool IsUnix
{
get
{
int p = (int)Environment.OSVersion.Platform;
return ((p == 4) || (p == 6) || (p == 128));
}
}
}
public class FileInfo
{
public string Name;
public string FullName;
public long LastWriteTime;
public long Length;
public FileInfo()
{ }
public FileInfo(string path)
{
FullName = path;
Name = Path.GetFileName(path);
if (unix.IsUnix)
{
System.IO.FileInfo fi = new System.IO.FileInfo(path);
if (!fi.Exists) return;
Length = fi.Length;
LastWriteTime = fi.LastWriteTimeUtc.Ticks;
return;
}
string fileName = NameFix.AddLongPathPrefix(path);
Win32Native.WIN32_FILE_ATTRIBUTE_DATA wIn32FileAttributeData = new Win32Native.WIN32_FILE_ATTRIBUTE_DATA();
bool b = Win32Native.GetFileAttributesEx(fileName, 0, ref wIn32FileAttributeData);
if (!b || (wIn32FileAttributeData.fileAttributes & Win32Native.FILE_ATTRIBUTE_DIRECTORY) != 0) return;
Length = Convert.Length(wIn32FileAttributeData.fileSizeHigh, wIn32FileAttributeData.fileSizeLow);
LastWriteTime = Convert.Time(wIn32FileAttributeData.ftLastWriteTimeHigh, wIn32FileAttributeData.ftLastWriteTimeLow);
}
}
public class DirectoryInfo
{
public string Name;
public string FullName;
public long LastWriteTime;
public DirectoryInfo()
{ }
public DirectoryInfo(string path)
{
FullName = path;
Name = Path.GetFileName(path);
if (unix.IsUnix)
{
System.IO.DirectoryInfo fi = new System.IO.DirectoryInfo(path);
if (!fi.Exists) return;
LastWriteTime = fi.LastWriteTimeUtc.Ticks;
return;
}
string fileName = NameFix.AddLongPathPrefix(path);
Win32Native.WIN32_FILE_ATTRIBUTE_DATA wIn32FileAttributeData = new Win32Native.WIN32_FILE_ATTRIBUTE_DATA();
bool b = Win32Native.GetFileAttributesEx(fileName, 0, ref wIn32FileAttributeData);
if (!b || (wIn32FileAttributeData.fileAttributes & Win32Native.FILE_ATTRIBUTE_DIRECTORY) == 0) return;
LastWriteTime = Convert.Time(wIn32FileAttributeData.ftLastWriteTimeHigh, wIn32FileAttributeData.ftLastWriteTimeLow);
}
public DirectoryInfo[] GetDirectories(bool includeHidden = true)
{
return GetDirectories("*", includeHidden);
}
public DirectoryInfo[] GetDirectories(string SearchPattern, bool includeHidden = true)
{
List<DirectoryInfo> dirs = new List<DirectoryInfo>();
if (unix.IsUnix)
{
System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(FullName);
System.IO.DirectoryInfo[] arrDi = di.GetDirectories(SearchPattern);
foreach (System.IO.DirectoryInfo tDi in arrDi)
{
DirectoryInfo lDi = new DirectoryInfo
{
Name = tDi.Name,
FullName = Path.Combine(FullName, tDi.Name),
LastWriteTime = tDi.LastWriteTimeUtc.Ticks
};
dirs.Add(lDi);
}
return dirs.ToArray();
}
string dirName = NameFix.AddLongPathPrefix(FullName);
Win32Native.WIN32_FIND_DATA findData = new Win32Native.WIN32_FIND_DATA();
SafeFindHandle findHandle = Win32Native.FindFirstFile(dirName + @"\" + SearchPattern, findData);
if (!findHandle.IsInvalid)
{
do
{
string currentFileName = findData.cFileName;
// if this is a directory, find its contents
if ((findData.dwFileAttributes & Win32Native.FILE_ATTRIBUTE_DIRECTORY) == 0) continue;
if (currentFileName == "." || currentFileName == "..") continue;
if (!includeHidden && (findData.dwFileAttributes & Win32Native.FILE_ATTRIBUTE_HIDDEN) != 0) continue;
DirectoryInfo di = new DirectoryInfo
{
Name = currentFileName,
FullName = Path.Combine(FullName, currentFileName),
LastWriteTime = Convert.Time(findData.ftLastWriteTimeHigh, findData.ftLastWriteTimeLow)
};
dirs.Add(di);
}
while (Win32Native.FindNextFile(findHandle, findData));
}
// close the find handle
findHandle.Dispose();
return dirs.ToArray();
}
public FileInfo[] GetFiles()
{
return GetFiles("*");
}
public FileInfo[] GetFiles(string SearchPattern, bool includeHidden = true)
{
List<FileInfo> files = new List<FileInfo>();
if (unix.IsUnix)
{
System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(FullName);
System.IO.FileInfo[] arrDi = di.GetFiles(SearchPattern);
foreach (System.IO.FileInfo tDi in arrDi)
{
FileInfo lDi = new FileInfo
{
Name = tDi.Name,
FullName = Path.Combine(FullName, tDi.Name),
Length = tDi.Length,
LastWriteTime = tDi.LastWriteTimeUtc.Ticks
};
files.Add(lDi);
}
return files.ToArray();
}
string dirName = NameFix.AddLongPathPrefix(FullName);
Win32Native.WIN32_FIND_DATA findData = new Win32Native.WIN32_FIND_DATA();
SafeFindHandle findHandle = Win32Native.FindFirstFile(dirName + @"\" + SearchPattern, findData);
if (!findHandle.IsInvalid)
{
do
{
string currentFileName = findData.cFileName;
// if this is a directory, find its contents
if ((findData.dwFileAttributes & Win32Native.FILE_ATTRIBUTE_DIRECTORY) != 0) continue;
if (!includeHidden && (findData.dwFileAttributes & Win32Native.FILE_ATTRIBUTE_HIDDEN) != 0) continue;
FileInfo fi = new FileInfo
{
Name = currentFileName,
FullName = Path.Combine(FullName, currentFileName),
Length = Convert.Length(findData.nFileSizeHigh, findData.nFileSizeLow),
LastWriteTime = Convert.Time(findData.ftLastWriteTimeHigh, findData.ftLastWriteTimeLow)
};
files.Add(fi);
}
while (Win32Native.FindNextFile(findHandle, findData));
}
// close the find handle
findHandle.Dispose();
return files.ToArray();
}
}
public static class Directory
{
public static bool Exists(string path)
{
if (unix.IsUnix)
return System.IO.Directory.Exists(path);
string fixPath = NameFix.AddLongPathPrefix(path);
Win32Native.WIN32_FILE_ATTRIBUTE_DATA wIn32FileAttributeData = new Win32Native.WIN32_FILE_ATTRIBUTE_DATA();
bool b = Win32Native.GetFileAttributesEx(fixPath, 0, ref wIn32FileAttributeData);
return b && (wIn32FileAttributeData.fileAttributes & Win32Native.FILE_ATTRIBUTE_DIRECTORY) != 0;
}
public static void Move(string sourceDirName, string destDirName)
{
if (unix.IsUnix)
{
System.IO.Directory.Move(sourceDirName, destDirName);
return;
}
if (sourceDirName == null)
throw new ArgumentNullException("sourceDirName");
if (sourceDirName.Length == 0)
throw new ArgumentException("Argument_EmptyFileName", "sourceDirName");
if (destDirName == null)
throw new ArgumentNullException("destDirName");
if (destDirName.Length == 0)
throw new ArgumentException("Argument_EmptyFileName", "destDirName");
string fullsourceDirName = NameFix.AddLongPathPrefix(sourceDirName);
string fulldestDirName = NameFix.AddLongPathPrefix(destDirName);
if (!Win32Native.MoveFile(fullsourceDirName, fulldestDirName))
{
int hr = Marshal.GetLastWin32Error();
if (hr == Win32Native.ERROR_FILE_NOT_FOUND) // Source dir not found
{
throw new Exception("ERROR_PATH_NOT_FOUND " + fullsourceDirName);
}
if (hr == Win32Native.ERROR_ACCESS_DENIED) // WinNT throws IOException. This check is for Win9x. We can't change it for backcomp.
{
throw new Exception("UnauthorizedAccess_IODenied_Path" + sourceDirName);
}
}
}
public static void Delete(string path)
{
if (unix.IsUnix)
{
System.IO.Directory.Delete(path);
return;
}
string fullPath = NameFix.AddLongPathPrefix(path);
Win32Native.RemoveDirectory(fullPath);
}
public static void CreateDirectory(string path)
{
if (unix.IsUnix)
{
System.IO.Directory.CreateDirectory(path);
return;
}
if (path == null)
throw new ArgumentNullException("path");
if (path.Length == 0)
throw new ArgumentException("Argument_PathEmpty");
string fullPath = NameFix.AddLongPathPrefix(path);
Win32Native.CreateDirectory(fullPath, IntPtr.Zero);
}
}
public static class File
{
public static bool Exists(string path)
{
if (unix.IsUnix)
return System.IO.File.Exists(path);
string fixPath = NameFix.AddLongPathPrefix(path);
Win32Native.WIN32_FILE_ATTRIBUTE_DATA wIn32FileAttributeData = new Win32Native.WIN32_FILE_ATTRIBUTE_DATA();
bool b = Win32Native.GetFileAttributesEx(fixPath, 0, ref wIn32FileAttributeData);
return b && (wIn32FileAttributeData.fileAttributes & Win32Native.FILE_ATTRIBUTE_DIRECTORY) == 0;
}
public static void Copy(string sourceFileName, string destfileName)
{
Copy(sourceFileName, destfileName, true);
}
public static void Copy(string sourceFileName, string destFileName, bool overwrite)
{
if (unix.IsUnix)
{
System.IO.File.Copy(sourceFileName, destFileName, overwrite);
return;
}
if (sourceFileName == null || destFileName == null)
throw new ArgumentNullException((sourceFileName == null ? "sourceFileName" : "destFileName"), "ArgumentNull_FileName");
if (sourceFileName.Length == 0 || destFileName.Length == 0)
throw new ArgumentException("Argument_EmptyFileName", (sourceFileName.Length == 0 ? "sourceFileName" : "destFileName"));
string fullSourceFileName = NameFix.AddLongPathPrefix(sourceFileName);
string fullDestFileName = NameFix.AddLongPathPrefix(destFileName);
bool r = Win32Native.CopyFile(fullSourceFileName, fullDestFileName, !overwrite);
if (!r)
{
// Save Win32 error because subsequent checks will overwrite this HRESULT.
int errorCode = Marshal.GetLastWin32Error();
string fileName = destFileName;
/*
if (errorCode != Win32Native.ERROR_FILE_EXISTS)
{
// For a number of error codes (sharing violation, path
// not found, etc) we don't know if the problem was with
// the source or dest file. Try reading the source file.
using (SafeFileHandle handle = Win32Native.UnsafeCreateFile(fullSourceFileName, FileStream.GENERIC_READ, FileShare.Read, null, FileMode.Open, 0, IntPtr.Zero))
{
if (handle.IsInvalid)
fileName = sourceFileName;
}
if (errorCode == Win32Native.ERROR_ACCESS_DENIED)
{
if (Directory.InternalExists(fullDestFileName))
throw new IOException(string.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Arg_FileIsDirectory_Name"), destFileName), Win32Native.ERROR_ACCESS_DENIED, fullDestFileName);
}
}
__Error.WinIOError(errorCode, fileName);
*/
}
}
public static void Move(string sourceFileName, string destFileName)
{
if (unix.IsUnix)
{
System.IO.File.Move(sourceFileName, destFileName);
return;
}
if (sourceFileName == null || destFileName == null)
throw new ArgumentNullException((sourceFileName == null ? "sourceFileName" : "destFileName"), "ArgumentNull_FileName");
if (sourceFileName.Length == 0 || destFileName.Length == 0)
throw new ArgumentException("Argument_EmptyFileName", (sourceFileName.Length == 0 ? "sourceFileName" : "destFileName"));
string fullSourceFileName = NameFix.AddLongPathPrefix(sourceFileName);
string fullDestFileName = NameFix.AddLongPathPrefix(destFileName);
if (!Exists(fullSourceFileName))
throw new Exception("ERROR_FILE_NOT_FOUND" + fullSourceFileName);
if (!Win32Native.MoveFile(fullSourceFileName, fullDestFileName))
{
int hr = Marshal.GetLastWin32Error();
throw new Exception(GetErrorCode(hr), new Exception("ERROR_MOVING_FILE. (" + fullSourceFileName + " to " + fullDestFileName + ")"));
}
}
public static void Delete(string path)
{
if (unix.IsUnix)
{
System.IO.File.Delete(path);
return;
}
string fixPath = NameFix.AddLongPathPrefix(path);
if (!Win32Native.DeleteFile(fixPath))
{
int hr = Marshal.GetLastWin32Error();
if (hr != Win32Native.ERROR_FILE_NOT_FOUND)
throw new Exception(GetErrorCode(hr), new Exception("ERROR_DELETING_FILE. (" + path + ")"));
}
}
private static string GetErrorCode(int hr)
{
switch (hr)
{
case 5: return "ERROR_ACCESS_DENIED: Access is denied.";
case 32: return "ERROR_FILE_IN_USE: The file is in use by another process.";
case 39: return "ERROR_HANDLE_DISK_FULL: The disk is full.";
case 112: return "ERROR_DISK_FULL: There is not enough space on the disk.";
case 123: return "ERROR_INVALID_NAME: The filename, directory name, or volume label syntax is incorrect.";
case 183: return "ERROR_ALREADY_EXISTS: Cannot create a file when that file already exists.";
}
return hr.ToString();
}
public static bool SetAttributes(string path, FileAttributes fileAttributes)
{
if (unix.IsUnix)
{
try
{
System.IO.File.SetAttributes(path, (System.IO.FileAttributes)fileAttributes);
return true;
}
catch (Exception)
{
return false;
}
}
string fullPath = NameFix.AddLongPathPrefix(path);
return Win32Native.SetFileAttributes(fullPath, (int)fileAttributes);
}
public static StreamWriter CreateText(string filename)
{
int errorCode = FileStream.OpenFileWrite(filename, out Stream fStream);
return errorCode != 0 ? null : new StreamWriter(fStream);
}
public static StreamReader OpenText(string filename, Encoding Enc)
{
int errorCode = FileStream.OpenFileRead(filename, out Stream fStream);
return errorCode != 0 ? null : new StreamReader(fStream, Enc);
}
private const int ERROR_INVALID_PARAMETER = 87;
private const int ERROR_ACCESS_DENIED = 0x5;
}
public static class Path
{
public static readonly char DirectorySeparatorChar = '\\';
public static readonly char AltDirectorySeparatorChar = '/';
public static readonly char VolumeSeparatorChar = ':';
public static string GetExtension(string path)
{
return System.IO.Path.GetExtension(path);
}
public static string Combine(string path1, string path2)
{
if (unix.IsUnix)
return System.IO.Path.Combine(path1, path2);
if (path1 == null || path2 == null)
throw new ArgumentNullException((path1 == null) ? "path1" : "path2");
//CheckInvalidPathChars(path1);
//CheckInvalidPathChars(path2);
if (path2.Length == 0)
return path1;
if (path1.Length == 0)
return path2;
if (IsPathRooted(path2))
return path2;
char ch = path1[path1.Length - 1];
if (ch != DirectorySeparatorChar && ch != AltDirectorySeparatorChar && ch != VolumeSeparatorChar)
return path1 + DirectorySeparatorChar + path2;
return path1 + path2;
}
private static bool IsPathRooted(string path)
{
if (path != null)
{
//CheckInvalidPathChars(path);
int length = path.Length;
if (
(length >= 1 && (path[0] == DirectorySeparatorChar ||
path[0] == AltDirectorySeparatorChar)) ||
(length >= 2 && path[1] == VolumeSeparatorChar)
) return true;
}
return false;
}
/*
private static void CheckInvalidPathChars(string path)
{
for (int index = 0; index < path.Length; ++index)
{
int num = path[index];
switch (num)
{
case 34:
case 60:
case 62:
case 124:
ReportError.SendErrorMessage("Invalid Character " + num + " in filename " + path);
continue;
default:
if (num >= 32)
continue;
goto case 34;
}
}
}
*/
public static string GetFileNameWithoutExtension(string path)
{
return System.IO.Path.GetFileNameWithoutExtension(path);
}
public static string GetFileName(string path)
{
return System.IO.Path.GetFileName(path);
}
public static string GetDirectoryName(string path)
{
if (unix.IsUnix)
return System.IO.Path.GetDirectoryName(path);
if (path != null)
{
int root = GetRootLength(path);
int i = path.Length;
if (i > root)
{
i = path.Length;
if (i == root) return null;
while (i > root && path[--i] != DirectorySeparatorChar && path[i] != AltDirectorySeparatorChar) ;
return path.Substring(0, i);
}
}
return null;
}
private static int GetRootLength(string path)
{
int i = 0;
int length = path.Length;
if (length >= 1 && (IsDirectorySeparator(path[0])))
{
// handles UNC names and directories off current drive's root.
i = 1;
if (length >= 2 && (IsDirectorySeparator(path[1])))
{
i = 2;
int n = 2;
while (i < length && ((path[i] != DirectorySeparatorChar && path[i] != AltDirectorySeparatorChar) || --n > 0)) i++;
}
}
else if (length >= 2 && path[1] == VolumeSeparatorChar)
{
// handles A:\foo.
i = 2;
if (length >= 3 && (IsDirectorySeparator(path[2]))) i++;
}
return i;
}
private static bool IsDirectorySeparator(char c)
{
return (c == DirectorySeparatorChar || c == AltDirectorySeparatorChar);
}
}
public static class FileStream
{
private const uint GENERIC_READ = 0x80000000;
private const uint GENERIC_WRITE = 0x40000000;
private const uint FILE_ATTRIBUTE_NORMAL = 0x80;
// errorMessage = new Win32Exception(errorCode).Message;
public static Stream OpenFileRead(string path, out int result)
{
result = OpenFileRead(path, out Stream stream);
return stream;
}
public static int OpenFileRead(string path, out Stream stream)
{
if (unix.IsUnix)
{
try
{
stream = new System.IO.FileStream(path, FileMode.Open, FileAccess.Read);
return 0;
}
catch (Exception)
{
stream = null;
return Marshal.GetLastWin32Error();
}
}
string filename = NameFix.AddLongPathPrefix(path);
SafeFileHandle hFile = Win32Native.CreateFile(filename,
GENERIC_READ,
System.IO.FileShare.Read,
IntPtr.Zero,
FileMode.Open,
FILE_ATTRIBUTE_NORMAL,
IntPtr.Zero);
if (hFile.IsInvalid)
{
stream = null;
return Marshal.GetLastWin32Error();
}
stream = new System.IO.FileStream(hFile, FileAccess.Read);
return 0;
}
public static int OpenFileWrite(string path, out Stream stream)
{
if (unix.IsUnix)
{
try
{
stream = new System.IO.FileStream(path, FileMode.Create, FileAccess.ReadWrite);
return 0;
}
catch (Exception)
{
stream = null;
return Marshal.GetLastWin32Error();
}
}
string filename = NameFix.AddLongPathPrefix(path);
SafeFileHandle hFile = Win32Native.CreateFile(filename,
GENERIC_READ | GENERIC_WRITE,
System.IO.FileShare.None,
IntPtr.Zero,
FileMode.Create,
FILE_ATTRIBUTE_NORMAL,
IntPtr.Zero);
if (hFile.IsInvalid)
{
stream = null;
return Marshal.GetLastWin32Error();
}
stream = new System.IO.FileStream(hFile, FileAccess.ReadWrite);
return 0;
}
}
public static class NameFix
{
public static string GetShortPath(string path)
{
if (unix.IsUnix)
return path;
int remove = 0;
string retPath;
if (path.StartsWith(@"\\"))
{
retPath = @"\\?\UNC\" + path.Substring(2);
remove = 8;
}
else
{
retPath = path;
if (path.Substring(1, 1) != ":")
retPath = Path.Combine(System.IO.Directory.GetCurrentDirectory(), retPath);
retPath = cleandots(retPath);
retPath = @"\\?\" + retPath;
remove = 4;
}
const int MAX_PATH = 300;
StringBuilder shortPath = new StringBuilder(MAX_PATH);
Win32Native.GetShortPathName(retPath, shortPath, MAX_PATH);
retPath = shortPath.ToString();
retPath = retPath.Substring(remove);
if (remove == 8) retPath = "\\" + retPath;
return retPath;
}
internal static string AddLongPathPrefix(string path)
{
if (string.IsNullOrEmpty(path) || path.StartsWith(@"\\?\"))
return path;
if (path.StartsWith(@"\\"))
return @"\\?\UNC\" + path.Substring(2);
string retPath = path;
if (path.Substring(1, 1) != ":")
retPath = Path.Combine(System.IO.Directory.GetCurrentDirectory(), retPath);
retPath = cleandots(retPath);
return @"\\?\" + retPath;
}
private static string cleandots(string path)
{
string retPath = path;
while (retPath.Contains(@"\..\"))
{
int index = retPath.IndexOf(@"\..\");
string path1 = retPath.Substring(0, index);
string path2 = retPath.Substring(index + 4);
int path1Back = path1.LastIndexOf(@"\");
retPath = path1.Substring(0, path1Back + 1) + path2;
}
return retPath;
}
}
}

View File

@@ -1,178 +0,0 @@
/******************************************************
* ROMVault3 is written by Gordon J. *
* Contact gordon@romvault.com *
* Copyright 2019 *
******************************************************/
using System;
using System.IO;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using System.Text;
using Microsoft.Win32.SafeHandles;
namespace RVIO
{
internal static class Win32Native
{
private const string KERNEL32 = "kernel32.dll";
public const int FILE_ATTRIBUTE_DIRECTORY = 0x00000010;
public const int FILE_ATTRIBUTE_HIDDEN = 0x00000002;
internal const int ERROR_FILE_NOT_FOUND = 0x2;
internal const int ERROR_ACCESS_DENIED = 0x5;
internal const int ERROR_FILE_EXISTS = 0x50;
[DllImport(KERNEL32, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)]
[ResourceExposure(ResourceScope.None)]
internal static extern bool GetFileAttributesEx(string fileName, int fileInfoLevel, ref WIN32_FILE_ATTRIBUTE_DATA lpFileInformation);
[DllImport(KERNEL32, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)]
[ResourceExposure(ResourceScope.None)]
internal static extern SafeFindHandle FindFirstFile(string fileName, [In] [Out] WIN32_FIND_DATA data);
[DllImport(KERNEL32, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)]
[ResourceExposure(ResourceScope.None)]
internal static extern bool FindNextFile(SafeFindHandle hndFindFile, [In] [Out] [MarshalAs(UnmanagedType.LPStruct)] WIN32_FIND_DATA lpFindFileData);
[DllImport(KERNEL32)]
[ResourceExposure(ResourceScope.None)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal static extern bool FindClose(IntPtr handle);
[DllImport(KERNEL32, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)]
[ResourceExposure(ResourceScope.Machine)]
internal static extern SafeFileHandle CreateFile(string lpFileName,
uint dwDesiredAccess, FileShare dwShareMode,
IntPtr securityAttrs, FileMode dwCreationDisposition,
uint dwFlagsAndAttributes, IntPtr hTemplateFile);
[DllImport(KERNEL32, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)]
[ResourceExposure(ResourceScope.Machine)]
internal static extern bool CreateDirectory(string path, IntPtr lpSecurityAttributes);
[DllImport(KERNEL32, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)]
[ResourceExposure(ResourceScope.Machine)]
internal static extern bool RemoveDirectory(string path);
[DllImport(KERNEL32, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)]
[ResourceExposure(ResourceScope.Machine)]
internal static extern bool CopyFile(string src, string dst, bool failIfExists);
[DllImport(KERNEL32, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)]
[ResourceExposure(ResourceScope.Machine)]
internal static extern bool MoveFile(string src, string dst);
[DllImport(KERNEL32, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)]
[ResourceExposure(ResourceScope.Machine)]
internal static extern bool DeleteFile(string path);
[DllImport(KERNEL32, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)]
[ResourceExposure(ResourceScope.None)]
internal static extern bool SetFileAttributes(string name, int attr);
[DllImport(KERNEL32, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)]
[ResourceExposure(ResourceScope.Machine)]
internal static extern int GetShortPathName(
[MarshalAs(UnmanagedType.LPTStr)] string path,
[MarshalAs(UnmanagedType.LPTStr)] StringBuilder shortPath,
int shortPathLength
);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
[BestFitMapping(false)]
internal class WIN32_FIND_DATA
{
internal int dwFileAttributes = 0;
internal uint ftCreationTimeLow;
internal uint ftCreationTimeHigh;
internal uint ftLastAccessTimeLow;
internal uint ftLastAccessTimeHigh;
internal uint ftLastWriteTimeLow;
internal uint ftLastWriteTimeHigh;
internal int nFileSizeHigh = 0;
internal int nFileSizeLow = 0;
internal int dwReserved0 = 0;
internal int dwReserved1 = 0;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] internal string cFileName = null;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] internal string cAlternateFileName = null;
}
[StructLayout(LayoutKind.Sequential)]
[Serializable]
internal struct WIN32_FILE_ATTRIBUTE_DATA
{
internal int fileAttributes;
internal uint ftCreationTimeLow;
internal uint ftCreationTimeHigh;
internal uint ftLastAccessTimeLow;
internal uint ftLastAccessTimeHigh;
internal uint ftLastWriteTimeLow;
internal uint ftLastWriteTimeHigh;
internal int fileSizeHigh;
internal int fileSizeLow;
}
}
internal sealed class SafeFindHandle : SafeHandleZeroOrMinusOneIsInvalid
{
[SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
internal SafeFindHandle() : base(true)
{
}
protected override bool ReleaseHandle()
{
return Win32Native.FindClose(handle);
}
}
internal static class Convert
{
private const long TicksPerMillisecond = 10000;
private const long TicksPerSecond = TicksPerMillisecond * 1000;
private const long TicksPerMinute = TicksPerSecond * 60;
private const long TicksPerHour = TicksPerMinute * 60;
private const long TicksPerDay = TicksPerHour * 24;
// Number of days in a non-leap year
private const int DaysPerYear = 365;
// Number of days in 4 years
private const int DaysPer4Years = DaysPerYear * 4 + 1;
// Number of days in 100 years
private const int DaysPer100Years = DaysPer4Years * 25 - 1;
// Number of days in 400 years
private const int DaysPer400Years = DaysPer100Years * 4 + 1;
// Number of days from 1/1/0001 to 12/31/1600
private const int DaysTo1601 = DaysPer400Years * 4;
public const long FileTimeOffset = DaysTo1601 * TicksPerDay;
// Number of days from 1/1/0001 to 12/31/9999
private const int DaysTo10000 = DaysPer400Years * 25 - 366;
private const long MinTicks = 0;
private const long MaxTicks = DaysTo10000 * TicksPerDay - 1;
public static long Length(int high, int low)
{
return ((long)high << 32) | (low & 0xFFFFFFFFL);
}
public static long Time(uint high, uint low)
{
return ((long)high << 32) | low;
}
}
}

View File

@@ -1,43 +0,0 @@
using System.IO;
using System.Text;
using SabreTools.Core;
namespace SabreTools.Library.FileTypes.Aaru
{
/// <summary>
/// Checksum entry, followed by checksum data itself
/// </summary>
/// <see cref="https://github.com/aaru-dps/Aaru/blob/master/Aaru.Images/AaruFormat/Structs.cs" />
public class ChecksumEntry
{
/// <summary>Checksum algorithm</summary>
public AaruChecksumAlgorithm type;
/// <summary>Length in bytes of checksum that follows this structure</summary>
public uint length;
/// <summary>Checksum that follows this structure</summary>
public byte[] checksum;
/// <summary>
/// Read a stream as an v
/// </summary>
/// <param name="stream">ChecksumEntry as a stream</param>
/// <returns>Populated ChecksumEntry, null on failure</returns>
public static ChecksumEntry Deserialize(Stream stream)
{
ChecksumEntry checksumEntry = new ChecksumEntry();
using (BinaryReader br = new BinaryReader(stream, Encoding.Default, true))
{
checksumEntry.type = (AaruChecksumAlgorithm)br.ReadByte();
checksumEntry.length = br.ReadUInt32();
if (checksumEntry.length == 0)
return null;
checksumEntry.checksum = br.ReadBytes((int)checksumEntry.length);
}
return checksumEntry;
}
}
}

View File

@@ -1,41 +0,0 @@
using System.IO;
using System.Text;
using SabreTools.Core;
namespace SabreTools.Library.FileTypes.Aaru
{
/// <summary>
/// Checksum block, contains a checksum of all user data sectors
/// (except for optical discs that is 2352 bytes raw sector if available
/// </summary>
/// <see cref="https://github.com/aaru-dps/Aaru/blob/master/Aaru.Images/AaruFormat/Structs.cs" />
public class ChecksumHeader
{
/// <summary>Identifier, <see cref="BlockType.ChecksumBlock" /></summary>
public AaruBlockType identifier;
/// <summary>Length in bytes of the block</summary>
public uint length;
/// <summary>How many checksums follow</summary>
public byte entries;
/// <summary>
/// Read a stream as an ChecksumHeader
/// </summary>
/// <param name="stream">ChecksumHeader as a stream</param>
/// <returns>Populated ChecksumHeader, null on failure</returns>
public static ChecksumHeader Deserialize(Stream stream)
{
ChecksumHeader checksumHeader = new ChecksumHeader();
using (BinaryReader br = new BinaryReader(stream, Encoding.Default, true))
{
checksumHeader.identifier = (AaruBlockType)br.ReadUInt32();
checksumHeader.length = br.ReadUInt32();
checksumHeader.entries = br.ReadByte();
}
return checksumHeader;
}
}
}

View File

@@ -1,40 +0,0 @@
using System.IO;
using System.Text;
using SabreTools.Core;
namespace SabreTools.Library.FileTypes.Aaru
{
/// <summary>
/// Index entry
/// </summary>
/// <see cref="https://github.com/aaru-dps/Aaru/blob/master/Aaru.Images/AaruFormat/Structs.cs" />
public class IndexEntry
{
/// <summary>Type of item pointed by this entry</summary>
public AaruBlockType blockType;
/// <summary>Type of data contained by the block pointed by this entry</summary>
public AaruDataType dataType;
/// <summary>Offset in file where item is stored</summary>
public ulong offset;
/// <summary>
/// Read a stream as an IndexHeader
/// </summary>
/// <param name="stream">IndexHeader as a stream</param>
/// <returns>Populated IndexHeader, null on failure</returns>
public static IndexEntry Deserialize(Stream stream)
{
IndexEntry indexEntry = new IndexEntry();
using (BinaryReader br = new BinaryReader(stream, Encoding.Default, true))
{
indexEntry.blockType = (AaruBlockType)br.ReadUInt32();
indexEntry.dataType = (AaruDataType)br.ReadUInt16();
indexEntry.offset = br.ReadUInt64();
}
return indexEntry;
}
}
}

View File

@@ -1,40 +0,0 @@
using System.IO;
using System.Text;
using SabreTools.Core;
namespace SabreTools.Library.FileTypes.Aaru
{
/// <summary>
/// Header for the index, followed by entries
/// </summary>
/// <see cref="https://github.com/aaru-dps/Aaru/blob/master/Aaru.Images/AaruFormat/Structs.cs" />
public class IndexHeader
{
/// <summary>Identifier, <see cref="BlockType.Index" /></summary>
public AaruBlockType identifier;
/// <summary>How many entries follow this header</summary>
public ushort entries;
/// <summary>CRC64-ECMA of the index</summary>
public ulong crc64;
/// <summary>
/// Read a stream as an IndexHeader
/// </summary>
/// <param name="stream">IndexHeader as a stream</param>
/// <returns>Populated IndexHeader, null on failure</returns>
public static IndexHeader Deserialize(Stream stream)
{
IndexHeader indexHeader = new IndexHeader();
using (BinaryReader br = new BinaryReader(stream, Encoding.Default, true))
{
indexHeader.identifier = (AaruBlockType)br.ReadUInt32();
indexHeader.entries = br.ReadUInt16();
indexHeader.crc64 = br.ReadUInt64();
}
return indexHeader;
}
}
}

View File

@@ -1,223 +0,0 @@
using System;
using System.IO;
using System.Text;
using SabreTools.IO;
using SabreTools.Core;
using SabreTools.Library.FileTypes.Aaru;
namespace SabreTools.Library.FileTypes
{
/// <summary>
/// AaruFormat code is based on the Aaru project
/// See https://github.com/aaru-dps/Aaru/tree/master/Aaru.Images/AaruFormat
/// </summary>
public class AaruFormat : BaseFile
{
#region Private instance variables
#region Header
protected ulong Identifier; // 'AARUFRMT' (0x544D524655524141)
protected string Application; // Name of application that created image
protected byte ImageMajorVersion; // Image format major version
protected byte ImageMinorVersion; // Image format minor version
protected byte ApplicationMajorVersion; // Major version of application that created image
protected byte ApplicationMinorVersion; // Minor version of application that created image
protected AaruMediaType MediaType; // Media type contained in image
protected ulong IndexOffset; // Offset to index
protected long CreationTime; // Windows filetime of creation time
protected long LastWrittenTime; // Windows filetime of last written time
#endregion
#region Internal Values
protected IndexHeader IndexHeader;
protected IndexEntry[] IndexEntries;
#endregion
#endregion // Private instance variables
#region Constructors
/// <summary>
/// Create a new AaruFormat from an input file
/// </summary>
/// <param name="filename">Filename respresenting the AaruFormat file</param>
public static AaruFormat Create(string filename)
{
using (FileStream fs = File.OpenRead(filename))
{
return Create(fs);
}
}
/// <summary>
/// Create a new AaruFormat from an input stream
/// </summary>
/// <param name="aarustream">Stream representing the AaruFormat file</param>
public static AaruFormat Create(Stream aarustream)
{
try
{
// Validate that this is actually a valid AaruFormat (by magic string alone)
bool validated = ValidateHeader(aarustream);
aarustream.SeekIfPossible(); // Seek back to start
if (!validated)
return null;
// Read and retrun the current AaruFormat
AaruFormat generated = Deserialize(aarustream);
if (generated != null)
generated.Type = FileType.AaruFormat;
return generated;
}
catch
{
return null;
}
}
#endregion
#region Header Parsing
/// <summary>
/// Validate we start with the right magic number
/// </summary>
public static bool ValidateHeader(Stream aarustream)
{
// Read the magic string
byte[] magicBytes = new byte[8];
int read = aarustream.Read(magicBytes, 0, 8);
// If we didn't read the magic fully, we don't have an AaruFormat
if (read < 8)
return false;
// If the bytes don't match, we don't have an AaruFormat
if (!magicBytes.StartsWith(Constants.AaruFormatSignature))
return false;
return true;
}
/// <summary>
/// Read a stream as an AaruFormat
/// </summary>
/// <param name="stream">AaruFormat file as a stream</param>
/// <returns>Populated AaruFormat file, null on failure</returns>
public static AaruFormat Deserialize(Stream stream)
{
try
{
AaruFormat aif = new AaruFormat();
using (BinaryReader br = new BinaryReader(stream, Encoding.Default, true))
{
aif.Identifier = br.ReadUInt64();
aif.Application = Encoding.Unicode.GetString(br.ReadBytes(64), 0, 64);
aif.ImageMajorVersion = br.ReadByte();
aif.ImageMinorVersion = br.ReadByte();
aif.ApplicationMajorVersion = br.ReadByte();
aif.ApplicationMinorVersion = br.ReadByte();
aif.MediaType = (AaruMediaType)br.ReadUInt32();
aif.IndexOffset = br.ReadUInt64();
aif.CreationTime = br.ReadInt64();
aif.LastWrittenTime = br.ReadInt64();
// If the offset is bigger than the stream, we can't read it
if (aif.IndexOffset > (ulong)stream.Length)
return null;
// Otherwise, we read in the index header
stream.Seek((long)aif.IndexOffset, SeekOrigin.Begin);
aif.IndexHeader = IndexHeader.Deserialize(stream);
if (aif.IndexHeader.entries == 0)
return null;
// Get the list of entries
aif.IndexEntries = new IndexEntry[aif.IndexHeader.entries];
for (ushort index = 0; index < aif.IndexHeader.entries; index++)
{
aif.IndexEntries[index] = IndexEntry.Deserialize(stream);
switch (aif.IndexEntries[index].blockType)
{
// We don't do anything with these block types currently
case AaruBlockType.DataBlock:
case AaruBlockType.DeDuplicationTable:
case AaruBlockType.Index:
case AaruBlockType.Index2:
case AaruBlockType.GeometryBlock:
case AaruBlockType.MetadataBlock:
case AaruBlockType.TracksBlock:
case AaruBlockType.CicmBlock:
case AaruBlockType.DataPositionMeasurementBlock:
case AaruBlockType.SnapshotBlock:
case AaruBlockType.ParentBlock:
case AaruBlockType.DumpHardwareBlock:
case AaruBlockType.TapeFileBlock:
case AaruBlockType.TapePartitionBlock:
case AaruBlockType.CompactDiscIndexesBlock:
// No-op
break;
// Read in all available hashes
case AaruBlockType.ChecksumBlock:
// If the offset is bigger than the stream, we can't read it
if (aif.IndexEntries[index].offset > (ulong)stream.Length)
return null;
// Otherwise, we read in the block
stream.Seek((long)aif.IndexEntries[index].offset, SeekOrigin.Begin);
ChecksumHeader checksumHeader = ChecksumHeader.Deserialize(stream);
if (checksumHeader.entries == 0)
return null;
// Read through each and pick out the ones we care about
for (byte entry = 0; entry < checksumHeader.entries; entry++)
{
ChecksumEntry checksumEntry = ChecksumEntry.Deserialize(stream);
if (checksumEntry == null)
continue;
switch (checksumEntry.type)
{
case AaruChecksumAlgorithm.Invalid:
break;
case AaruChecksumAlgorithm.Md5:
aif.MD5 = checksumEntry.checksum;
break;
case AaruChecksumAlgorithm.Sha1:
aif.SHA1 = checksumEntry.checksum;
break;
case AaruChecksumAlgorithm.Sha256:
aif.SHA256 = checksumEntry.checksum;
break;
case AaruChecksumAlgorithm.SpamSum:
aif.SpamSum = checksumEntry.checksum;
break;
}
}
// Once we got hashes, we return early
return aif;
}
}
}
return aif;
}
catch
{
// We don't care what the error was at this point
return null;
}
}
#endregion
}
}

View File

@@ -1,167 +0,0 @@
using System.Collections.Generic;
using System.IO;
using SabreTools.Core;
namespace SabreTools.Library.FileTypes
{
public abstract class BaseArchive : Folder
{
#region Fields
/// <summary>
/// Determines if dates are read or written
/// </summary>
public bool UseDates { get; set; } = false;
#endregion
#region Protected instance variables
/// <summary>
/// Buffer size used by archives
/// </summary>
protected const int _bufferSize = 4096 * 128;
#endregion
#region Construtors
/// <summary>
/// Create a new Archive with no base file
/// </summary>
public BaseArchive()
{
}
/// <summary>
/// Create a new Archive from the given file
/// </summary>
/// <param name="filename">Name of the file to use as an archive</param>
/// <param name="getHashes">True if hashes for this file should be calculated, false otherwise (default)</param>
public BaseArchive(string filename, bool getHashes = false)
: base(filename, getHashes)
{
}
/// <summary>
/// Create an archive object from a filename, if possible
/// </summary>
/// <param name="input">Name of the file to create the archive from</param>
/// <returns>Archive object representing the inputs</returns>
public static BaseArchive Create(string input)
{
BaseArchive archive = null;
// First get the archive type
FileType? at = GetFileType(input);
// If we got back null, then it's not an archive, so we we return
if (at == null)
return archive;
// Create the archive based on the type
staticLogger.Verbose($"Found archive of type: {at}");
switch (at)
{
case FileType.GZipArchive:
archive = new GZipArchive(input);
break;
case FileType.RarArchive:
archive = new RarArchive(input);
break;
case FileType.SevenZipArchive:
archive = new SevenZipArchive(input);
break;
case FileType.TapeArchive:
archive = new TapeArchive(input);
break;
case FileType.ZipArchive:
archive = new ZipArchive(input);
break;
default:
// We ignore all other types for now
break;
}
return archive;
}
/// <summary>
/// Create an archive object of the specified type, if possible
/// </summary>
/// <param name="archiveType">SharpCompress.Common.ArchiveType representing the archive to create</param>
/// <returns>Archive object representing the inputs</returns>
public static BaseArchive Create(FileType archiveType)
{
switch (archiveType)
{
case FileType.GZipArchive:
return new GZipArchive();
case FileType.RarArchive:
return new RarArchive();
case FileType.SevenZipArchive:
return new SevenZipArchive();
case FileType.TapeArchive:
return new TapeArchive();
case FileType.ZipArchive:
return new ZipArchive();
default:
return null;
}
}
#endregion
#region Extraction
/// <inheritdoc/>
public override abstract bool CopyAll(string outDir);
/// <inheritdoc/>
public override abstract string CopyToFile(string entryName, string outDir);
/// <inheritdoc/>
public override abstract (MemoryStream, string) CopyToStream(string entryName);
#endregion
#region Information
/// <inheritdoc/>
public override abstract List<BaseFile> GetChildren();
/// <inheritdoc/>
public override abstract List<string> GetEmptyFolders();
/// <summary>
/// Check whether the input file is a standardized format
/// </summary>
public abstract bool IsTorrent();
#endregion
#region Writing
/// <inheritdoc/>
public override abstract bool Write(string inputFile, string outDir, BaseFile baseFile);
/// <inheritdoc/>
public override abstract bool Write(Stream inputStream, string outDir, BaseFile baseFile);
/// <inheritdoc/>
public override abstract bool Write(List<string> inputFiles, string outDir, List<BaseFile> baseFiles);
#endregion
}
}

View File

@@ -1,428 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using SabreTools.Core;
using SabreTools.IO;
using SabreTools.Library.IO;
using SabreTools.Logging;
using Compress.ThreadReaders;
namespace SabreTools.Library.FileTypes
{
public class BaseFile
{
// TODO: Get all of these values automatically so there is no public "set"
#region Fields
/// <summary>
/// Internal type of the represented file
/// </summary>
public FileType Type { get; protected set; }
/// <summary>
/// Filename or path to the file
/// </summary>
public string Filename { get; set; }
/// <summary>
/// Direct parent of the file
/// </summary>
public string Parent { get; set; }
/// <summary>
/// Date stamp of the file
/// </summary>
public string Date { get; set; }
/// <summary>
/// Optional size of the file
/// </summary>
public long? Size { get; set; }
/// <summary>
/// Hashes that are available for the file
/// </summary>
public Hash AvailableHashes { get; set; } = Hash.Standard;
/// <summary>
/// CRC32 hash of the file
/// </summary>
public byte[] CRC { get; set; } = null;
/// <summary>
/// MD5 hash of the file
/// </summary>
public byte[] MD5 { get; set; } = null;
#if NET_FRAMEWORK
/// <summary>
/// RIPEMD160 hash of the file
/// </summary>
public byte[] RIPEMD160 { get; set; } = null;
#endif
/// <summary>
/// SHA-1 hash of the file
/// </summary>
public byte[] SHA1 { get; set; } = null;
/// <summary>
/// SHA-256 hash of the file
/// </summary>
public byte[] SHA256 { get; set; } = null;
/// <summary>
/// SHA-384 hash of the file
/// </summary>
public byte[] SHA384 { get; set; } = null;
/// <summary>
/// SHA-512 hash of the file
/// </summary>
public byte[] SHA512 { get; set; } = null;
/// <summary>
/// SpamSum fuzzy hash of the file
/// </summary>
public byte[] SpamSum { get; set; } = null;
#endregion
#region Construtors
/// <summary>
/// Create a new BaseFile with no base file
/// </summary>
public BaseFile()
{
}
/// <summary>
/// Create a new BaseFile from the given file
/// </summary>
/// <param name="filename">Name of the file to use</param>
/// <param name="getHashes">True if hashes for this file should be calculated (default), false otherwise</param>
public BaseFile(string filename, bool getHashes = true)
{
this.Filename = filename;
if (getHashes)
{
BaseFile temp = GetInfo(this.Filename, hashes: this.AvailableHashes);
if (temp != null)
{
this.Parent = temp.Parent;
this.Date = temp.Date;
this.CRC = temp.CRC;
this.MD5 = temp.MD5;
#if NET_FRAMEWORK
this.RIPEMD160 = temp.RIPEMD160;
#endif
this.SHA1 = temp.SHA1;
this.SHA256 = temp.SHA256;
this.SHA384 = temp.SHA384;
this.SHA512 = temp.SHA512;
this.SpamSum = temp.SpamSum;
}
}
}
/// <summary>
/// Create a new BaseFile from the given file
/// </summary>
/// <param name="filename">Name of the file to use</param>
/// <param name="stream">Stream to populate information from</param>
/// <param name="getHashes">True if hashes for this file should be calculated (default), false otherwise</param>
public BaseFile(string filename, Stream stream, bool getHashes = true)
{
this.Filename = filename;
if (getHashes)
{
BaseFile temp = GetInfo(stream, hashes: this.AvailableHashes);
if (temp != null)
{
this.Parent = temp.Parent;
this.Date = temp.Date;
this.CRC = temp.CRC;
this.MD5 = temp.MD5;
#if NET_FRAMEWORK
this.RIPEMD160 = temp.RIPEMD160;
#endif
this.SHA1 = temp.SHA1;
this.SHA256 = temp.SHA256;
this.SHA384 = temp.SHA384;
this.SHA512 = temp.SHA512;
this.SpamSum = temp.SpamSum;
}
}
}
#endregion
#region Static Methods
/// <summary>
/// Returns the file type of an input file
/// </summary>
/// <param name="input">Input file to check</param>
/// <returns>FileType of inputted file (null on error)</returns>
public static FileType? GetFileType(string input)
{
FileType? outFileType = null;
// If the file is null, then we have no archive type
if (input == null)
return outFileType;
// First line of defense is going to be the extension, for better or worse
if (!PathExtensions.HasValidArchiveExtension(input))
return outFileType;
// Read the first bytes of the file and get the magic number
BinaryReader br = new BinaryReader(File.OpenRead(input));
byte[] magic = br.ReadBytes(8);
br.Dispose();
// Now try to match it to a known signature
if (magic.StartsWith(Constants.SevenZipSignature))
{
outFileType = FileType.SevenZipArchive;
}
else if (magic.StartsWith(Constants.AaruFormatSignature))
{
outFileType = FileType.AaruFormat;
}
else if (magic.StartsWith(Constants.CHDSignature))
{
outFileType = FileType.CHD;
}
else if (magic.StartsWith(Constants.GzSignature))
{
outFileType = FileType.GZipArchive;
}
else if (magic.StartsWith(Constants.LRZipSignature))
{
outFileType = FileType.LRZipArchive;
}
else if (magic.StartsWith(Constants.LZ4Signature)
|| magic.StartsWith(Constants.LZ4SkippableMinSignature)
|| magic.StartsWith(Constants.LZ4SkippableMaxSignature))
{
outFileType = FileType.LZ4Archive;
}
else if (magic.StartsWith(Constants.RarSignature)
|| magic.StartsWith(Constants.RarFiveSignature))
{
outFileType = FileType.RarArchive;
}
else if (magic.StartsWith(Constants.TarSignature)
|| magic.StartsWith(Constants.TarZeroSignature))
{
outFileType = FileType.TapeArchive;
}
else if (magic.StartsWith(Constants.XZSignature))
{
outFileType = FileType.XZArchive;
}
else if (magic.StartsWith(Constants.ZipSignature)
|| magic.StartsWith(Constants.ZipSignatureEmpty)
|| magic.StartsWith(Constants.ZipSignatureSpanned))
{
outFileType = FileType.ZipArchive;
}
else if (magic.StartsWith(Constants.ZPAQSignature))
{
outFileType = FileType.ZPAQArchive;
}
else if (magic.StartsWith(Constants.ZstdSignature))
{
outFileType = FileType.ZstdArchive;
}
return outFileType;
}
/// <summary>
/// Retrieve file information for a single file
/// </summary>
/// <param name="input">Filename to get information from</param>
/// <param name="header">Populated string representing the name of the skipper to use, a blank string to use the first available checker, null otherwise</param>
/// <param name="hashes">Hashes to include in the information</param>
/// <param name="asFiles">TreatAsFiles representing special format scanning</param>
/// <returns>Populated BaseFile object if success, empty one on error</returns>
public static BaseFile GetInfo(string input, string header = null, Hash hashes = Hash.Standard, TreatAsFile asFiles = 0x00)
{
// Add safeguard if file doesn't exist
if (!File.Exists(input))
return null;
// Get input information
var fileType = GetFileType(input);
Stream inputStream = File.OpenRead(input);
// Try to match the supplied header skipper
if (header != null)
{
var rule = Transform.GetMatchingRule(input, Path.GetFileNameWithoutExtension(header));
// If there's a match, transform the stream before getting info
if (rule.Tests != null && rule.Tests.Count != 0)
{
// Create the output stream
MemoryStream outputStream = new MemoryStream();
// Transform the stream and get the information from it
rule.TransformStream(inputStream, outputStream, keepReadOpen: false, keepWriteOpen: true);
inputStream = outputStream;
}
}
// Get the info in the proper manner
BaseFile baseFile;
if (fileType == FileType.AaruFormat && !asFiles.HasFlag(TreatAsFile.AaruFormat))
baseFile = AaruFormat.Create(inputStream);
else if (fileType == FileType.CHD && !asFiles.HasFlag(TreatAsFile.CHD))
baseFile = CHDFile.Create(inputStream);
else
baseFile = GetInfo(inputStream, hashes: hashes, keepReadOpen: false);
// Dispose of the input stream
inputStream?.Dispose();
// Add unique data from the file
baseFile.Filename = Path.GetFileName(input);
baseFile.Date = new FileInfo(input).LastWriteTime.ToString("yyyy/MM/dd HH:mm:ss");
return baseFile;
}
/// <summary>
/// Retrieve file information for a single file
/// </summary>
/// <param name="input">Filename to get information from</param>
/// <param name="size">Size of the input stream</param>
/// <param name="hashes">Hashes to include in the information</param>
/// <param name="keepReadOpen">True if the underlying read stream should be kept open, false otherwise</param>
/// <returns>Populated BaseFile object if success, empty one on error</returns>
public static BaseFile GetInfo(Stream input, long size = -1, Hash hashes = Hash.Standard, bool keepReadOpen = false)
{
// If we want to automatically set the size
if (size == -1)
size = input.Length;
try
{
// Get a list of hashers to run over the buffer
List<Hasher> hashers = new List<Hasher>();
if (hashes.HasFlag(Hash.CRC))
hashers.Add(new Hasher(Hash.CRC));
if (hashes.HasFlag(Hash.MD5))
hashers.Add(new Hasher(Hash.MD5));
#if NET_FRAMEWORK
if (hashes.HasFlag(Hash.RIPEMD160))
hashers.Add(new Hasher(Hash.RIPEMD160));
#endif
if (hashes.HasFlag(Hash.SHA1))
hashers.Add(new Hasher(Hash.SHA1));
if (hashes.HasFlag(Hash.SHA256))
hashers.Add(new Hasher(Hash.SHA256));
if (hashes.HasFlag(Hash.SHA384))
hashers.Add(new Hasher(Hash.SHA384));
if (hashes.HasFlag(Hash.SHA512))
hashers.Add(new Hasher(Hash.SHA512));
if (hashes.HasFlag(Hash.SpamSum))
hashers.Add(new Hasher(Hash.SpamSum));
// Initialize the hashing helpers
var loadBuffer = new ThreadLoadBuffer(input);
int buffersize = 3 * 1024 * 1024;
byte[] buffer0 = new byte[buffersize];
byte[] buffer1 = new byte[buffersize];
/*
Please note that some of the following code is adapted from
RomVault. This is a modified version of how RomVault does
threaded hashing. As such, some of the terminology and code
is the same, though variable names and comments may have
been tweaked to better fit this code base.
*/
// Pre load the first buffer
long refsize = size;
int next = refsize > buffersize ? buffersize : (int)refsize;
input.Read(buffer0, 0, next);
int current = next;
refsize -= next;
bool bufferSelect = true;
while (current > 0)
{
// Trigger the buffer load on the second buffer
next = refsize > buffersize ? buffersize : (int)refsize;
if (next > 0)
loadBuffer.Trigger(bufferSelect ? buffer1 : buffer0, next);
byte[] buffer = bufferSelect ? buffer0 : buffer1;
// Run hashes in parallel
Parallel.ForEach(hashers, Globals.ParallelOptions, h => h.Process(buffer, current));
// Wait for the load buffer worker, if needed
if (next > 0)
loadBuffer.Wait();
// Setup for the next hashing step
current = next;
refsize -= next;
bufferSelect = !bufferSelect;
}
// Finalize all hashing helpers
loadBuffer.Finish();
Parallel.ForEach(hashers, Globals.ParallelOptions, h => h.Finalize());
// Get the results
BaseFile baseFile = new BaseFile()
{
Size = size,
CRC = hashes.HasFlag(Hash.CRC) ? hashers.First(h => h.HashType == Hash.CRC).GetHash() : null,
MD5 = hashes.HasFlag(Hash.MD5) ? hashers.First(h => h.HashType == Hash.MD5).GetHash() : null,
#if NET_FRAMEWORK
RIPEMD160 = hashes.HasFlag(Hash.RIPEMD160) ? hashers.First(h => h.HashType == Hash.RIPEMD160).GetHash() : null,
#endif
SHA1 = hashes.HasFlag(Hash.SHA1) ? hashers.First(h => h.HashType == Hash.SHA1).GetHash() : null,
SHA256 = hashes.HasFlag(Hash.SHA256) ? hashers.First(h => h.HashType == Hash.SHA256).GetHash() : null,
SHA384 = hashes.HasFlag(Hash.SHA384) ? hashers.First(h => h.HashType == Hash.SHA384).GetHash() : null,
SHA512 = hashes.HasFlag(Hash.SHA512) ? hashers.First(h => h.HashType == Hash.SHA512).GetHash() : null,
SpamSum = hashes.HasFlag(Hash.SpamSum) ? hashers.First(h => h.HashType == Hash.SpamSum).GetHash() : null,
};
// Dispose of the hashers
loadBuffer.Dispose();
hashers.ForEach(h => h.Dispose());
return baseFile;
}
catch (IOException ex)
{
LoggerImpl.Warning(ex, "An exception occurred during hashing.");
return new BaseFile();
}
finally
{
if (!keepReadOpen)
input.Dispose();
else
input.SeekIfPossible();
}
}
#endregion
}
}

Some files were not shown because too many files have changed in this diff Show More