mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-07-08 18:16:30 +00:00
more allocation reductions
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
@@ -10,18 +11,23 @@ using Decoder = SharpCompress.Compressors.LZMA.RangeCoder.Decoder;
|
||||
|
||||
namespace SharpCompress.Compressors.PPMd.H;
|
||||
|
||||
internal class ModelPpm
|
||||
internal class ModelPpm : IDisposable
|
||||
{
|
||||
private const int SEE2_CONTEXT_ROWS = 25;
|
||||
private const int SEE2_CONTEXT_COLUMNS = 16;
|
||||
private const int SEE2_CONTEXT_SIZE = SEE2_CONTEXT_ROWS * SEE2_CONTEXT_COLUMNS;
|
||||
private const int BIN_SUMM_ROWS = 128;
|
||||
private const int BIN_SUMM_COLUMNS = 64;
|
||||
private const int BIN_SUMM_SIZE = BIN_SUMM_ROWS * BIN_SUMM_COLUMNS;
|
||||
|
||||
private void InitBlock()
|
||||
{
|
||||
for (var i = 0; i < 25; i++)
|
||||
for (var i = 0; i < SEE2_CONTEXT_SIZE; i++)
|
||||
{
|
||||
_see2Cont[i] = new See2Context[16];
|
||||
}
|
||||
for (var i2 = 0; i2 < 128; i2++)
|
||||
{
|
||||
_binSumm[i2] = new int[64];
|
||||
_see2Cont[i] = new See2Context();
|
||||
}
|
||||
|
||||
_binSumm = ArrayPool<int>.Shared.Rent(BIN_SUMM_SIZE);
|
||||
}
|
||||
|
||||
public SubAllocator SubAlloc { get; } = new();
|
||||
@@ -68,8 +74,6 @@ internal class ModelPpm
|
||||
set => _hiBitsFlag = value & 0xff;
|
||||
}
|
||||
|
||||
public virtual int[][] BinSumm => _binSumm;
|
||||
|
||||
internal RangeCoder Coder { get; private set; }
|
||||
|
||||
internal State FoundState { get; private set; }
|
||||
@@ -95,9 +99,9 @@ internal class ModelPpm
|
||||
|
||||
public const int MAX_FREQ = 124;
|
||||
|
||||
private readonly See2Context[][] _see2Cont = new See2Context[25][];
|
||||
private readonly See2Context[] _see2Cont = new See2Context[SEE2_CONTEXT_SIZE];
|
||||
|
||||
private See2Context _dummySee2Cont;
|
||||
private readonly See2Context _dummySee2Cont = new();
|
||||
|
||||
private PpmContext _minContext; //medContext
|
||||
|
||||
@@ -112,18 +116,12 @@ internal class ModelPpm
|
||||
|
||||
private readonly int[] _charMask = new int[256];
|
||||
|
||||
private readonly int[] _ns2Indx = new int[256];
|
||||
|
||||
private readonly int[] _ns2BsIndx = new int[256];
|
||||
|
||||
private readonly int[] _hb2Flag = new int[256];
|
||||
|
||||
// byte EscCount, PrevSuccess, HiBitsFlag;
|
||||
private int _escCount,
|
||||
_prevSuccess,
|
||||
_hiBitsFlag;
|
||||
|
||||
private readonly int[][] _binSumm = new int[128][]; // binary SEE-contexts
|
||||
private int[] _binSumm; // binary SEE-contexts
|
||||
|
||||
private static readonly int[] INIT_BIN_ESC =
|
||||
{
|
||||
@@ -137,6 +135,61 @@ internal class ModelPpm
|
||||
0x6051,
|
||||
};
|
||||
|
||||
private static readonly int[] NS2_INDX = CreateNs2Indx();
|
||||
|
||||
private static readonly int[] NS2_BS_INDX = CreateNs2BsIndx();
|
||||
|
||||
private static readonly int[] HB2_FLAG = CreateHb2Flag();
|
||||
|
||||
private static int[] CreateNs2Indx()
|
||||
{
|
||||
var result = new int[256];
|
||||
int i,
|
||||
k,
|
||||
m,
|
||||
step;
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
result[i] = i;
|
||||
}
|
||||
for (m = i, k = 1, step = 1; i < 256; i++)
|
||||
{
|
||||
result[i] = m;
|
||||
if (--k == 0)
|
||||
{
|
||||
k = ++step;
|
||||
m++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static int[] CreateNs2BsIndx()
|
||||
{
|
||||
var result = new int[256];
|
||||
result[0] = 0;
|
||||
result[1] = 2;
|
||||
for (var j = 0; j < 9; j++)
|
||||
{
|
||||
result[2 + j] = 4;
|
||||
}
|
||||
for (var j = 0; j < 256 - 11; j++)
|
||||
{
|
||||
result[11 + j] = 6;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static int[] CreateHb2Flag()
|
||||
{
|
||||
var result = new int[256];
|
||||
for (var j = 0; j < 0x100 - 0x40; j++)
|
||||
{
|
||||
result[0x40 + j] = 0x08;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// 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 readonly State _tempState1 = new(null);
|
||||
@@ -171,6 +224,8 @@ internal class ModelPpm
|
||||
//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 readonly int[] _ps = new int[MAX_O];
|
||||
|
||||
private bool _isDisposed;
|
||||
|
||||
public ModelPpm()
|
||||
{
|
||||
InitBlock();
|
||||
@@ -180,6 +235,23 @@ internal class ModelPpm
|
||||
//medContext = null;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_isDisposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_isDisposed = true;
|
||||
SubAlloc.StopSubAllocator();
|
||||
var binSumm = _binSumm;
|
||||
if (binSumm is not null)
|
||||
{
|
||||
_binSumm = null;
|
||||
ArrayPool<int>.Shared.Return(binSumm, clearArray: true);
|
||||
}
|
||||
}
|
||||
|
||||
private void RestartModelRare()
|
||||
{
|
||||
new Span<int>(_charMask).Clear();
|
||||
@@ -209,67 +281,30 @@ internal class ModelPpm
|
||||
state.SetSuccessor(0);
|
||||
}
|
||||
|
||||
for (var i = 0; i < 128; i++)
|
||||
for (var i = 0; i < BIN_SUMM_ROWS; i++)
|
||||
{
|
||||
for (var k = 0; k < 8; k++)
|
||||
{
|
||||
for (var m = 0; m < 64; m += 8)
|
||||
for (var m = 0; m < BIN_SUMM_COLUMNS; m += 8)
|
||||
{
|
||||
_binSumm[i][k + m] = BIN_SCALE - (INIT_BIN_ESC[k] / (i + 2));
|
||||
SetBinSumm(i, k + m, BIN_SCALE - (INIT_BIN_ESC[k] / (i + 2)));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < 25; i++)
|
||||
for (var i = 0; i < SEE2_CONTEXT_ROWS; i++)
|
||||
{
|
||||
for (var k = 0; k < 16; k++)
|
||||
for (var k = 0; k < SEE2_CONTEXT_COLUMNS; k++)
|
||||
{
|
||||
_see2Cont[i][k].Initialize((5 * i) + 10);
|
||||
GetSee2Cont(i, k).Initialize((5 * i) + 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void StartModelRare(int maxOrder)
|
||||
{
|
||||
int i,
|
||||
k,
|
||||
m,
|
||||
step;
|
||||
_escCount = 1;
|
||||
_maxOrder = maxOrder;
|
||||
RestartModelRare();
|
||||
|
||||
// Bug Fixed
|
||||
_ns2BsIndx[0] = 0;
|
||||
_ns2BsIndx[1] = 2;
|
||||
for (var j = 0; j < 9; j++)
|
||||
{
|
||||
_ns2BsIndx[2 + j] = 4;
|
||||
}
|
||||
for (var 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 (var j = 0; j < 0x40; j++)
|
||||
{
|
||||
_hb2Flag[j] = 0;
|
||||
}
|
||||
for (var j = 0; j < 0x100 - 0x40; j++)
|
||||
{
|
||||
_hb2Flag[0x40 + j] = 0x08;
|
||||
}
|
||||
_dummySee2Cont.Shift = PERIOD_BITS;
|
||||
}
|
||||
|
||||
@@ -320,14 +355,6 @@ internal class ModelPpm
|
||||
//medContext = new PPMContext(Heap);
|
||||
_maxContext = new PpmContext(Heap);
|
||||
FoundState = new State(Heap);
|
||||
_dummySee2Cont = new See2Context();
|
||||
for (var i = 0; i < 25; i++)
|
||||
{
|
||||
for (var j = 0; j < 16; j++)
|
||||
{
|
||||
_see2Cont[i][j] = new See2Context();
|
||||
}
|
||||
}
|
||||
StartModelRare(maxOrder);
|
||||
}
|
||||
return (_minContext.Address != 0);
|
||||
@@ -379,14 +406,6 @@ internal class ModelPpm
|
||||
|
||||
_maxContext = new PpmContext(Heap);
|
||||
FoundState = new State(Heap);
|
||||
_dummySee2Cont = new See2Context();
|
||||
for (var i = 0; i < 25; i++)
|
||||
{
|
||||
for (var j = 0; j < 16; j++)
|
||||
{
|
||||
_see2Cont[i][j] = new See2Context();
|
||||
}
|
||||
}
|
||||
StartModelRare(maxOrder);
|
||||
}
|
||||
return _minContext.Address != 0;
|
||||
@@ -532,17 +551,24 @@ internal class ModelPpm
|
||||
return (symbol);
|
||||
}
|
||||
|
||||
public virtual See2Context[][] GetSee2Cont() => _see2Cont;
|
||||
public virtual See2Context GetSee2Cont(int row, int column) =>
|
||||
_see2Cont[(row * SEE2_CONTEXT_COLUMNS) + column];
|
||||
|
||||
public virtual int GetBinSumm(int row, int column) =>
|
||||
_binSumm[(row * BIN_SUMM_COLUMNS) + column];
|
||||
|
||||
public virtual void SetBinSumm(int row, int column, int value) =>
|
||||
_binSumm[(row * BIN_SUMM_COLUMNS) + column] = value;
|
||||
|
||||
public virtual void IncEscCount(int dEscCount) => EscCount += dEscCount;
|
||||
|
||||
public virtual void IncRunLength(int dRunLength) => RunLength += dRunLength;
|
||||
|
||||
public virtual int[] GetHb2Flag() => _hb2Flag;
|
||||
public virtual int[] GetHb2Flag() => HB2_FLAG;
|
||||
|
||||
public virtual int[] GetNs2BsIndx() => _ns2BsIndx;
|
||||
public virtual int[] GetNs2BsIndx() => NS2_BS_INDX;
|
||||
|
||||
public virtual int[] GetNs2Indx() => _ns2Indx;
|
||||
public virtual int[] GetNs2Indx() => NS2_INDX;
|
||||
|
||||
private int CreateSuccessors(bool skip, State p1)
|
||||
{
|
||||
@@ -906,14 +932,6 @@ internal class ModelPpm
|
||||
//medContext = new PPMContext(Heap);
|
||||
_maxContext = new PpmContext(Heap);
|
||||
FoundState = new State(Heap);
|
||||
_dummySee2Cont = new See2Context();
|
||||
for (var i = 0; i < 25; i++)
|
||||
{
|
||||
for (var j = 0; j < 16; j++)
|
||||
{
|
||||
_see2Cont[i][j] = new See2Context();
|
||||
}
|
||||
}
|
||||
StartModelRare(maxOrder);
|
||||
|
||||
return (_minContext.Address != 0);
|
||||
@@ -943,14 +961,6 @@ internal class ModelPpm
|
||||
//medContext = new PPMContext(Heap);
|
||||
_maxContext = new PpmContext(Heap);
|
||||
FoundState = new State(Heap);
|
||||
_dummySee2Cont = new See2Context();
|
||||
for (var i = 0; i < 25; i++)
|
||||
{
|
||||
for (var j = 0; j < 16; j++)
|
||||
{
|
||||
_see2Cont[i][j] = new See2Context();
|
||||
}
|
||||
}
|
||||
StartModelRare(maxOrder);
|
||||
|
||||
return (_minContext.Address != 0);
|
||||
@@ -1010,7 +1020,7 @@ internal class ModelPpm
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
_hiBitsFlag = _hb2Flag[FoundState.Symbol];
|
||||
_hiBitsFlag = GetHb2Flag()[FoundState.Symbol];
|
||||
decoder.Decode((uint)hiCnt, (uint)(_minContext.FreqData.SummFreq - hiCnt));
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
@@ -1031,12 +1041,15 @@ internal class ModelPpm
|
||||
_hiBitsFlag = GetHb2Flag()[FoundState.Symbol];
|
||||
var off1 = rs.Freq - 1;
|
||||
var off2 = _minContext.GetArrayIndex(this, rs);
|
||||
var bs = _binSumm[off1][off2];
|
||||
var bs = GetBinSumm(off1, off2);
|
||||
if (decoder.DecodeBit((uint)bs, 14) == 0)
|
||||
{
|
||||
byte symbol;
|
||||
_binSumm[off1][off2] =
|
||||
(bs + INTERVAL - _minContext.GetMean(bs, PERIOD_BITS, 2)) & 0xFFFF;
|
||||
SetBinSumm(
|
||||
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);
|
||||
@@ -1046,7 +1059,7 @@ internal class ModelPpm
|
||||
return symbol;
|
||||
}
|
||||
bs = (bs - _minContext.GetMean(bs, PERIOD_BITS, 2)) & 0xFFFF;
|
||||
_binSumm[off1][off2] = bs;
|
||||
SetBinSumm(off1, off2, bs);
|
||||
_initEsc = PpmContext.EXP_ESCAPE[Utility.URShift(bs, 10)];
|
||||
int i;
|
||||
for (i = 0; i < 256; i++)
|
||||
@@ -1172,7 +1185,7 @@ internal class ModelPpm
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
_hiBitsFlag = _hb2Flag[FoundState.Symbol];
|
||||
_hiBitsFlag = GetHb2Flag()[FoundState.Symbol];
|
||||
await decoder
|
||||
.DecodeAsync(
|
||||
(uint)hiCnt,
|
||||
@@ -1199,15 +1212,18 @@ internal class ModelPpm
|
||||
_hiBitsFlag = GetHb2Flag()[FoundState.Symbol];
|
||||
var off1 = rs.Freq - 1;
|
||||
var off2 = _minContext.GetArrayIndex(this, rs);
|
||||
var bs = _binSumm[off1][off2];
|
||||
var bs = GetBinSumm(off1, off2);
|
||||
if (
|
||||
await decoder.DecodeBitAsync((uint)bs, 14, cancellationToken).ConfigureAwait(false)
|
||||
== 0
|
||||
)
|
||||
{
|
||||
byte symbol;
|
||||
_binSumm[off1][off2] =
|
||||
(bs + INTERVAL - _minContext.GetMean(bs, PERIOD_BITS, 2)) & 0xFFFF;
|
||||
SetBinSumm(
|
||||
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);
|
||||
@@ -1217,7 +1233,7 @@ internal class ModelPpm
|
||||
return symbol;
|
||||
}
|
||||
bs = (bs - _minContext.GetMean(bs, PERIOD_BITS, 2)) & 0xFFFF;
|
||||
_binSumm[off1][off2] = bs;
|
||||
SetBinSumm(off1, off2, bs);
|
||||
_initEsc = PpmContext.EXP_ESCAPE[Utility.URShift(bs, 10)];
|
||||
int i;
|
||||
for (i = 0; i < 256; i++)
|
||||
|
||||
@@ -265,7 +265,7 @@ internal class PpmContext : Pointer
|
||||
model.HiBitsFlag = model.GetHb2Flag()[model.FoundState.Symbol];
|
||||
var off1 = rs.Freq - 1;
|
||||
var off2 = GetArrayIndex(model, rs);
|
||||
var bs = model.BinSumm[off1][off2];
|
||||
var bs = model.GetBinSumm(off1, off2);
|
||||
if (model.Coder.GetCurrentShiftCount(ModelPpm.TOT_BITS) < bs)
|
||||
{
|
||||
model.FoundState.Address = rs.Address;
|
||||
@@ -273,7 +273,7 @@ internal class PpmContext : Pointer
|
||||
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.SetBinSumm(off1, off2, bs);
|
||||
model.PrevSuccess = 1;
|
||||
model.IncRunLength(1);
|
||||
}
|
||||
@@ -281,7 +281,7 @@ internal class PpmContext : Pointer
|
||||
{
|
||||
model.Coder.SubRange.LowCount = bs;
|
||||
bs = (bs - GetMean(bs, ModelPpm.PERIOD_BITS, 2)) & 0xFFFF;
|
||||
model.BinSumm[off1][off2] = bs;
|
||||
model.SetBinSumm(off1, off2, bs);
|
||||
model.Coder.SubRange.HighCount = ModelPpm.BIN_SCALE;
|
||||
model.InitEsc = EXP_ESCAPE[Utility.URShift(bs, 10)];
|
||||
model.NumMasked = 1;
|
||||
@@ -431,7 +431,7 @@ internal class PpmContext : Pointer
|
||||
idx2 += 2 * ((_freqData.SummFreq < 11 * numStats) ? 1 : 0);
|
||||
idx2 += 4 * ((model.NumMasked > diff) ? 1 : 0);
|
||||
idx2 += model.HiBitsFlag;
|
||||
psee2C = model.GetSee2Cont()[idx1][idx2];
|
||||
psee2C = model.GetSee2Cont(idx1, idx2);
|
||||
model.Coder.SubRange.Scale = psee2C.Mean;
|
||||
}
|
||||
else
|
||||
@@ -457,7 +457,7 @@ internal class PpmContext : Pointer
|
||||
idx2 += 2 * ((_freqData.SummFreq < 11 * numStats) ? 1 : 0);
|
||||
idx2 += 4 * ((numMasked > nonMasked) ? 1 : 0);
|
||||
idx2 += model.HiBitsFlag;
|
||||
psee2C = model.GetSee2Cont()[idx1][idx2];
|
||||
psee2C = model.GetSee2Cont(idx1, idx2);
|
||||
escFreq = psee2C.Mean;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Text;
|
||||
|
||||
namespace SharpCompress.Compressors.PPMd.H;
|
||||
|
||||
internal class SubAllocator
|
||||
internal class SubAllocator : IDisposable
|
||||
{
|
||||
public virtual int FakeUnitsStart
|
||||
{
|
||||
@@ -124,21 +125,32 @@ internal class SubAllocator
|
||||
{
|
||||
if (_subAllocatorSize != 0)
|
||||
{
|
||||
var heap = _heap;
|
||||
_subAllocatorSize = 0;
|
||||
|
||||
//ArrayFactory.BYTES_FACTORY.recycle(heap);
|
||||
_heap = null;
|
||||
_heapStart = 1;
|
||||
|
||||
// rarfree(HeapStart);
|
||||
for (var i = 0; i < _freeList.Length; i++)
|
||||
{
|
||||
_freeList[i] = null;
|
||||
}
|
||||
|
||||
// Free temp fields
|
||||
_tempRarNode = null;
|
||||
_tempRarMemBlock1 = null;
|
||||
_tempRarMemBlock2 = null;
|
||||
_tempRarMemBlock3 = null;
|
||||
|
||||
if (heap is not null)
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(heap, clearArray: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose() => StopSubAllocator();
|
||||
|
||||
public virtual int GetAllocatedMemory() => _subAllocatorSize;
|
||||
|
||||
public virtual bool StartSubAllocator(int saSize)
|
||||
@@ -159,7 +171,8 @@ internal class SubAllocator
|
||||
_tempMemBlockPos = realAllocSize;
|
||||
realAllocSize += RarMemBlock.SIZE;
|
||||
|
||||
_heap = new byte[realAllocSize];
|
||||
_heap = ArrayPool<byte>.Shared.Rent(realAllocSize);
|
||||
new Span<byte>(_heap, 0, realAllocSize).Clear();
|
||||
_heapStart = 1;
|
||||
_heapEnd = _heapStart + allocSize - UNIT_SIZE;
|
||||
_subAllocatorSize = t;
|
||||
|
||||
@@ -182,6 +182,8 @@ public class PpmdStream : Stream, IAsyncDisposable
|
||||
{
|
||||
_model.EncodeBlock(_stream, Stream.Null, true);
|
||||
}
|
||||
_modelH?.Dispose();
|
||||
_modelH = null;
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
@@ -202,6 +204,8 @@ public class PpmdStream : Stream, IAsyncDisposable
|
||||
{
|
||||
await _model.EncodeBlockAsync(_stream, new MemoryStream(), true).ConfigureAwait(false);
|
||||
}
|
||||
_modelH?.Dispose();
|
||||
_modelH = null;
|
||||
|
||||
#if !LEGACY_DOTNET || NETSTANDARD2_1
|
||||
await base.DisposeAsync().ConfigureAwait(false);
|
||||
|
||||
@@ -27,8 +27,16 @@ internal sealed partial class Unpack
|
||||
this.writeStream = writeStream;
|
||||
if (!fileHeader.IsSolid)
|
||||
{
|
||||
Init();
|
||||
if (fileHeader.IsStored)
|
||||
{
|
||||
ReleaseWindow();
|
||||
}
|
||||
else
|
||||
{
|
||||
Init();
|
||||
}
|
||||
}
|
||||
|
||||
suspended = false;
|
||||
await DoUnpackAsync(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
@@ -40,6 +48,7 @@ internal sealed partial class Unpack
|
||||
await UnstoreFileAsync(cancellationToken).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (fileHeader.CompressionAlgorithm)
|
||||
{
|
||||
case 15:
|
||||
@@ -77,6 +86,7 @@ internal sealed partial class Unpack
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
code = code < destUnpSize ? code : (int)destUnpSize;
|
||||
await writeStream
|
||||
.WriteAsync(buffer, 0, code, cancellationToken)
|
||||
@@ -122,6 +132,7 @@ internal sealed partial class Unpack
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
(!solid || !tablesRead)
|
||||
&& !await ReadTablesAsync(cancellationToken).ConfigureAwait(false)
|
||||
@@ -155,12 +166,14 @@ internal sealed partial class Unpack
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (suspended)
|
||||
{
|
||||
FileExtracted = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (unpBlockType == BlockTypes.BLOCK_PPM)
|
||||
{
|
||||
var Ch = await ppm.DecodeCharAsync(cancellationToken).ConfigureAwait(false);
|
||||
@@ -169,6 +182,7 @@ internal sealed partial class Unpack
|
||||
ppmError = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (Ch == PpmEscChar)
|
||||
{
|
||||
var NextCh = await ppm.DecodeCharAsync(cancellationToken).ConfigureAwait(false);
|
||||
@@ -178,20 +192,25 @@ internal sealed partial class Unpack
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (NextCh == 2 || NextCh == -1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (NextCh == 3)
|
||||
{
|
||||
if (!await ReadVMCodePPMAsync(cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (NextCh == 4)
|
||||
{
|
||||
int Distance = 0,
|
||||
@@ -217,13 +236,16 @@ internal sealed partial class Unpack
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (failed)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
CopyString(Length + 32, Distance + 2);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (NextCh == 5)
|
||||
{
|
||||
var Length = await ppm.DecodeCharAsync(cancellationToken)
|
||||
@@ -232,10 +254,12 @@ internal sealed partial class Unpack
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
CopyString(Length + 4, 1);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
window[unpPtr++] = (byte)Ch;
|
||||
continue;
|
||||
}
|
||||
@@ -246,6 +270,7 @@ internal sealed partial class Unpack
|
||||
window[unpPtr++] = (byte)Number;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Number >= 271)
|
||||
{
|
||||
var Length = LDecode[Number -= 271] + 3;
|
||||
@@ -266,6 +291,7 @@ internal sealed partial class Unpack
|
||||
Distance += ((Utility.URShift(GetBits(), (20 - Bits))) << 4);
|
||||
AddBits(Bits - 4);
|
||||
}
|
||||
|
||||
if (lowDistRepCount > 0)
|
||||
{
|
||||
lowDistRepCount--;
|
||||
@@ -307,30 +333,37 @@ internal sealed partial class Unpack
|
||||
CopyString(Length, Distance);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Number == 256)
|
||||
{
|
||||
if (!await ReadEndOfBlockAsync(cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Number == 257)
|
||||
{
|
||||
if (!await ReadVMCodeAsync(cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Number == 258)
|
||||
{
|
||||
if (lastLength != 0)
|
||||
{
|
||||
CopyString(lastLength, lastDist);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Number < 263)
|
||||
{
|
||||
var DistNum = Number - 259;
|
||||
@@ -339,6 +372,7 @@ internal sealed partial class Unpack
|
||||
{
|
||||
oldDist[I] = oldDist[I - 1];
|
||||
}
|
||||
|
||||
oldDist[0] = Distance;
|
||||
|
||||
var LengthNumber = this.decodeNumber(RD);
|
||||
@@ -348,10 +382,12 @@ internal sealed partial class Unpack
|
||||
Length += Utility.URShift(GetBits(), (16 - Bits));
|
||||
AddBits(Bits);
|
||||
}
|
||||
|
||||
InsertLastMatch(Length, Distance);
|
||||
CopyString(Length, Distance);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Number < 272)
|
||||
{
|
||||
var Distance = SDDecode[Number -= 263] + 1;
|
||||
@@ -360,11 +396,13 @@ internal sealed partial class Unpack
|
||||
Distance += Utility.URShift(GetBits(), (16 - Bits));
|
||||
AddBits(Bits);
|
||||
}
|
||||
|
||||
InsertOldDist(Distance);
|
||||
InsertLastMatch(2, Distance);
|
||||
CopyString(2, Distance);
|
||||
}
|
||||
}
|
||||
|
||||
await UnpWriteBufAsync(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@@ -379,11 +417,13 @@ internal sealed partial class Unpack
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (flt.NextWindow)
|
||||
{
|
||||
flt.NextWindow = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
var BlockStart = flt.BlockStart;
|
||||
var BlockLength = flt.BlockLength;
|
||||
if (((BlockStart - WrittenBorder) & PackDef.MAXWINMASK) < WriteSize)
|
||||
@@ -395,6 +435,7 @@ internal sealed partial class Unpack
|
||||
WrittenBorder = BlockStart;
|
||||
WriteSize = (unpPtr - WrittenBorder) & PackDef.MAXWINMASK;
|
||||
}
|
||||
|
||||
if (BlockLength <= WriteSize)
|
||||
{
|
||||
var BlockEnd = (BlockStart + BlockLength) & PackDef.MAXWINMASK;
|
||||
@@ -526,6 +567,7 @@ internal sealed partial class Unpack
|
||||
ArrayPool<byte>.Shared.Return(FilteredData);
|
||||
FilteredData = ArrayPool<byte>.Shared.Rent(FilteredDataSize);
|
||||
}
|
||||
|
||||
for (var i = 0; i < FilteredDataSize; i++)
|
||||
{
|
||||
FilteredData[i] = NextPrg.GlobalData[FilteredDataOffset + i];
|
||||
@@ -558,6 +600,7 @@ internal sealed partial class Unpack
|
||||
filt.NextWindow = false;
|
||||
}
|
||||
}
|
||||
|
||||
wrPtr = WrittenBorder;
|
||||
return;
|
||||
}
|
||||
@@ -603,11 +646,13 @@ internal sealed partial class Unpack
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var writeSize = size;
|
||||
if (writeSize > destUnpSize)
|
||||
{
|
||||
writeSize = (int)destUnpSize;
|
||||
}
|
||||
|
||||
await writeStream
|
||||
.WriteAsync(data, offset, writeSize, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
@@ -786,6 +831,7 @@ internal sealed partial class Unpack
|
||||
NewTable = (BitField & 0x4000) != 0;
|
||||
AddBits(2);
|
||||
}
|
||||
|
||||
tablesRead = !NewTable;
|
||||
return !(
|
||||
NewFile || NewTable && !await ReadTablesAsync(cancellationToken).ConfigureAwait(false)
|
||||
@@ -819,9 +865,11 @@ internal sealed partial class Unpack
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
vmCode.Add((byte)(GetBits() >> 8));
|
||||
AddBits(8);
|
||||
}
|
||||
|
||||
return AddVMCode(FirstByte, vmCode);
|
||||
}
|
||||
|
||||
@@ -831,6 +879,7 @@ internal sealed partial class Unpack
|
||||
{
|
||||
await unpReadBufAsync(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return InBuf[inAddr++] & 0xff;
|
||||
}
|
||||
|
||||
@@ -841,6 +890,7 @@ internal sealed partial class Unpack
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var Length = (FirstByte & 7) + 1;
|
||||
if (Length == 7)
|
||||
{
|
||||
@@ -849,6 +899,7 @@ internal sealed partial class Unpack
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Length = B1 + 7;
|
||||
}
|
||||
else if (Length == 8)
|
||||
@@ -858,11 +909,13 @@ internal sealed partial class Unpack
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var B2 = await ppm.DecodeCharAsync(cancellationToken).ConfigureAwait(false);
|
||||
if (B2 == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Length = (B1 * 256) + B2;
|
||||
}
|
||||
|
||||
@@ -874,8 +927,10 @@ internal sealed partial class Unpack
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
vmCode.Add((byte)Ch);
|
||||
}
|
||||
|
||||
return AddVMCode(FirstByte, vmCode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,16 +27,22 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
if (!disposed)
|
||||
{
|
||||
base.Dispose();
|
||||
if (window is not null)
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(window);
|
||||
window = null;
|
||||
}
|
||||
ReleaseWindow();
|
||||
rarVM.Dispose();
|
||||
ppm.Dispose();
|
||||
disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void ReleaseWindow()
|
||||
{
|
||||
if (window is not null)
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(window);
|
||||
window = null;
|
||||
}
|
||||
}
|
||||
|
||||
public bool FileExtracted { get; private set; }
|
||||
|
||||
public long DestSize
|
||||
@@ -61,6 +67,7 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
{
|
||||
unpReadBuf();
|
||||
}
|
||||
|
||||
return (InBuf[inAddr++] & 0xff);
|
||||
}
|
||||
|
||||
@@ -127,6 +134,7 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
{
|
||||
this.window = ArrayPool<byte>.Shared.Rent(PackDef.MAXWINSIZE);
|
||||
}
|
||||
|
||||
inAddr = 0;
|
||||
UnpInitData(false);
|
||||
}
|
||||
@@ -139,8 +147,16 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
this.writeStream = writeStream;
|
||||
if (!fileHeader.IsSolid)
|
||||
{
|
||||
Init();
|
||||
if (fileHeader.IsStored)
|
||||
{
|
||||
ReleaseWindow();
|
||||
}
|
||||
else
|
||||
{
|
||||
Init();
|
||||
}
|
||||
}
|
||||
|
||||
suspended = false;
|
||||
DoUnpack();
|
||||
}
|
||||
@@ -152,6 +168,7 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
UnstoreFile();
|
||||
return;
|
||||
}
|
||||
|
||||
switch (fileHeader.CompressionAlgorithm)
|
||||
{
|
||||
case 15: // rar 1.5 compression
|
||||
@@ -189,6 +206,7 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
code = code < destUnpSize ? code : (int)destUnpSize;
|
||||
writeStream.Write(buffer.Slice(0, code));
|
||||
destUnpSize -= code;
|
||||
@@ -227,6 +245,7 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ((!solid || !tablesRead) && !ReadTables())
|
||||
{
|
||||
return;
|
||||
@@ -259,12 +278,14 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (suspended)
|
||||
{
|
||||
FileExtracted = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (unpBlockType == BlockTypes.BLOCK_PPM)
|
||||
{
|
||||
var Ch = ppm.DecodeChar();
|
||||
@@ -273,6 +294,7 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
ppmError = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (Ch == PpmEscChar)
|
||||
{
|
||||
var NextCh = ppm.DecodeChar();
|
||||
@@ -282,20 +304,25 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (NextCh == 2 || NextCh == -1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (NextCh == 3)
|
||||
{
|
||||
if (!ReadVMCodePPM())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (NextCh == 4)
|
||||
{
|
||||
int Distance = 0,
|
||||
@@ -322,13 +349,16 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (failed)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
CopyString(Length + 32, Distance + 2);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (NextCh == 5)
|
||||
{
|
||||
var Length = ppm.DecodeChar();
|
||||
@@ -336,10 +366,12 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
CopyString(Length + 4, 1);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
window[unpPtr++] = (byte)Ch;
|
||||
continue;
|
||||
}
|
||||
@@ -350,6 +382,7 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
window[unpPtr++] = (byte)Number;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Number >= 271)
|
||||
{
|
||||
var Length = LDecode[Number -= 271] + 3;
|
||||
@@ -370,6 +403,7 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
Distance += ((Utility.URShift(GetBits(), (20 - Bits))) << 4);
|
||||
AddBits(Bits - 4);
|
||||
}
|
||||
|
||||
if (lowDistRepCount > 0)
|
||||
{
|
||||
lowDistRepCount--;
|
||||
@@ -412,30 +446,37 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
CopyString(Length, Distance);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Number == 256)
|
||||
{
|
||||
if (!ReadEndOfBlock())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Number == 257)
|
||||
{
|
||||
if (!ReadVMCode())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Number == 258)
|
||||
{
|
||||
if (lastLength != 0)
|
||||
{
|
||||
CopyString(lastLength, lastDist);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Number < 263)
|
||||
{
|
||||
var DistNum = Number - 259;
|
||||
@@ -444,6 +485,7 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
{
|
||||
oldDist[I] = oldDist[I - 1];
|
||||
}
|
||||
|
||||
oldDist[0] = Distance;
|
||||
|
||||
var LengthNumber = this.decodeNumber(RD);
|
||||
@@ -453,10 +495,12 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
Length += Utility.URShift(GetBits(), (16 - Bits));
|
||||
AddBits(Bits);
|
||||
}
|
||||
|
||||
InsertLastMatch(Length, Distance);
|
||||
CopyString(Length, Distance);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Number < 272)
|
||||
{
|
||||
var Distance = SDDecode[Number -= 263] + 1;
|
||||
@@ -465,11 +509,13 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
Distance += Utility.URShift(GetBits(), (16 - Bits));
|
||||
AddBits(Bits);
|
||||
}
|
||||
|
||||
InsertOldDist(Distance);
|
||||
InsertLastMatch(2, Distance);
|
||||
CopyString(2, Distance);
|
||||
}
|
||||
}
|
||||
|
||||
UnpWriteBuf();
|
||||
}
|
||||
|
||||
@@ -484,11 +530,13 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (flt.NextWindow)
|
||||
{
|
||||
flt.NextWindow = false; // ->NextWindow=false;
|
||||
continue;
|
||||
}
|
||||
|
||||
var BlockStart = flt.BlockStart; // ->BlockStart;
|
||||
var BlockLength = flt.BlockLength; // ->BlockLength;
|
||||
if (((BlockStart - WrittenBorder) & PackDef.MAXWINMASK) < WriteSize)
|
||||
@@ -499,6 +547,7 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
WrittenBorder = BlockStart;
|
||||
WriteSize = (unpPtr - WrittenBorder) & PackDef.MAXWINMASK;
|
||||
}
|
||||
|
||||
if (BlockLength <= WriteSize)
|
||||
{
|
||||
var BlockEnd = (BlockStart + BlockLength) & PackDef.MAXWINMASK;
|
||||
@@ -652,6 +701,7 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
ArrayPool<byte>.Shared.Return(FilteredData);
|
||||
FilteredData = ArrayPool<byte>.Shared.Rent(FilteredDataSize);
|
||||
}
|
||||
|
||||
for (var i = 0; i < FilteredDataSize; i++)
|
||||
{
|
||||
FilteredData[i] = NextPrg.GlobalData[FilteredDataOffset + i];
|
||||
@@ -682,6 +732,7 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
filt.NextWindow = false;
|
||||
}
|
||||
}
|
||||
|
||||
wrPtr = WrittenBorder;
|
||||
return;
|
||||
}
|
||||
@@ -713,11 +764,13 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var writeSize = size;
|
||||
if (writeSize > destUnpSize)
|
||||
{
|
||||
writeSize = (int)destUnpSize;
|
||||
}
|
||||
|
||||
writeStream.Write(data, offset, writeSize);
|
||||
|
||||
writtenFileSize += size;
|
||||
@@ -767,6 +820,7 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
{
|
||||
window[unpPtr + i] = window[destPtr + i];
|
||||
}
|
||||
|
||||
unpPtr += length;
|
||||
}
|
||||
else
|
||||
@@ -800,6 +854,7 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
|
||||
InitFilters();
|
||||
}
|
||||
|
||||
InitBitInput();
|
||||
ppmError = false;
|
||||
writtenFileSize = 0;
|
||||
@@ -864,6 +919,7 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
NewTable = (BitField & 0x4000) != 0;
|
||||
AddBits(2);
|
||||
}
|
||||
|
||||
tablesRead = !NewTable;
|
||||
return !(NewFile || NewTable && !ReadTables());
|
||||
}
|
||||
@@ -880,6 +936,7 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
|
||||
AddBits((8 - inBit) & 7);
|
||||
long bitField = GetBits() & unchecked((int)0xffFFffFF);
|
||||
if ((bitField & 0x8000) != 0)
|
||||
@@ -887,6 +944,7 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
unpBlockType = BlockTypes.BLOCK_PPM;
|
||||
return (ppm.DecodeInit(this, PpmEscChar));
|
||||
}
|
||||
|
||||
unpBlockType = BlockTypes.BLOCK_LZ;
|
||||
|
||||
prevLowDist = 0;
|
||||
@@ -896,6 +954,7 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
{
|
||||
new Span<byte>(unpOldTable).Clear(); // memset(UnpOldTable,0,sizeof(UnpOldTable));
|
||||
}
|
||||
|
||||
AddBits(2);
|
||||
|
||||
for (var i = 0; i < PackDef.BC; i++)
|
||||
@@ -917,6 +976,7 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
{
|
||||
bitLength[i++] = 0;
|
||||
}
|
||||
|
||||
i--;
|
||||
}
|
||||
}
|
||||
@@ -939,6 +999,7 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
|
||||
var Number = this.decodeNumber(BD);
|
||||
if (Number < 16)
|
||||
{
|
||||
@@ -958,6 +1019,7 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
N = (Utility.URShift(GetBits(), 9)) + 11;
|
||||
AddBits(7);
|
||||
}
|
||||
|
||||
while (N-- > 0 && i < TableSize)
|
||||
{
|
||||
table[i] = table[i - 1];
|
||||
@@ -977,17 +1039,20 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
N = (Utility.URShift(GetBits(), 9)) + 11;
|
||||
AddBits(7);
|
||||
}
|
||||
|
||||
while (N-- > 0 && i < TableSize)
|
||||
{
|
||||
table[i++] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tablesRead = true;
|
||||
if (inAddr > readTop)
|
||||
{
|
||||
return (false);
|
||||
}
|
||||
|
||||
UnpackUtility.makeDecodeTables(table, 0, LD, PackDef.NC);
|
||||
UnpackUtility.makeDecodeTables(table, PackDef.NC, DD, PackDef.DC);
|
||||
UnpackUtility.makeDecodeTables(table, PackDef.NC + PackDef.DC, LDD, PackDef.LDC);
|
||||
@@ -1027,9 +1092,11 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
{
|
||||
return (false);
|
||||
}
|
||||
|
||||
vmCode.Add((byte)(GetBits() >> 8));
|
||||
AddBits(8);
|
||||
}
|
||||
|
||||
return AddVMCode(FirstByte, vmCode);
|
||||
}
|
||||
|
||||
@@ -1040,6 +1107,7 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
{
|
||||
return (false);
|
||||
}
|
||||
|
||||
var Length = (FirstByte & 7) + 1;
|
||||
if (Length == 7)
|
||||
{
|
||||
@@ -1048,6 +1116,7 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
{
|
||||
return (false);
|
||||
}
|
||||
|
||||
Length = B1 + 7;
|
||||
}
|
||||
else if (Length == 8)
|
||||
@@ -1057,11 +1126,13 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
{
|
||||
return (false);
|
||||
}
|
||||
|
||||
var B2 = ppm.DecodeChar();
|
||||
if (B2 == -1)
|
||||
{
|
||||
return (false);
|
||||
}
|
||||
|
||||
Length = (B1 * 256) + B2;
|
||||
}
|
||||
|
||||
@@ -1073,8 +1144,10 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
{
|
||||
return (false);
|
||||
}
|
||||
|
||||
vmCode.Add((byte)Ch); // VMCode[I]=Ch;
|
||||
}
|
||||
|
||||
return AddVMCode(FirstByte, vmCode);
|
||||
}
|
||||
|
||||
@@ -1111,6 +1184,7 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
{
|
||||
return (false);
|
||||
}
|
||||
|
||||
lastFilter = FiltPos;
|
||||
var NewFilter = (FiltPos == filters.Count);
|
||||
|
||||
@@ -1151,6 +1225,7 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
{
|
||||
BlockStart += 258;
|
||||
}
|
||||
|
||||
StackFilter.BlockStart = ((BlockStart + unpPtr) & PackDef.MAXWINMASK);
|
||||
if ((firstByte & 0x20) != 0)
|
||||
{
|
||||
@@ -1161,6 +1236,7 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
StackFilter.BlockLength =
|
||||
FiltPos < oldFilterLengths.Count ? oldFilterLengths[FiltPos] : 0;
|
||||
}
|
||||
|
||||
StackFilter.NextWindow =
|
||||
(wrPtr != unpPtr) && ((wrPtr - unpPtr) & PackDef.MAXWINMASK) <= BlockStart;
|
||||
|
||||
@@ -1223,6 +1299,7 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
ArrayPool<byte>.Shared.Return(VMCode);
|
||||
}
|
||||
}
|
||||
|
||||
StackFilter.Program.AltCommands = Filter.Program.Commands; // StackFilter->Prg.AltCmd=&Filter->Prg.Cmd[0];
|
||||
StackFilter.Program.CommandCount = Filter.Program.CommandCount;
|
||||
|
||||
@@ -1272,6 +1349,7 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
{
|
||||
globalData[0x30 + i] = 0x0;
|
||||
}
|
||||
|
||||
if ((firstByte & 8) != 0)
|
||||
// put data block passed as parameter if any
|
||||
{
|
||||
@@ -1279,11 +1357,13 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
{
|
||||
return (false);
|
||||
}
|
||||
|
||||
var DataSize = RarVM.ReadData(Inp);
|
||||
if (DataSize > RarVM.VM_GLOBALMEMSIZE - RarVM.VM_FIXEDGLOBALSIZE)
|
||||
{
|
||||
return (false);
|
||||
}
|
||||
|
||||
var CurSize = StackFilter.Program.GlobalData.Count;
|
||||
if (CurSize < DataSize + RarVM.VM_FIXEDGLOBALSIZE)
|
||||
{
|
||||
@@ -1292,6 +1372,7 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
DataSize + RarVM.VM_FIXEDGLOBALSIZE - CurSize
|
||||
);
|
||||
}
|
||||
|
||||
var offset = RarVM.VM_FIXEDGLOBALSIZE;
|
||||
globalData = StackFilter.Program.GlobalData;
|
||||
for (var I = 0; I < DataSize; I++)
|
||||
@@ -1300,10 +1381,12 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
{
|
||||
return (false);
|
||||
}
|
||||
|
||||
globalData[offset + I] = (byte)(Utility.URShift(Inp.GetBits(), 8));
|
||||
Inp.AddBits(8);
|
||||
}
|
||||
}
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
@@ -1331,10 +1414,6 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
|
||||
|
||||
private void CleanUp()
|
||||
{
|
||||
if (ppm != null)
|
||||
{
|
||||
var allocator = ppm.SubAlloc;
|
||||
allocator?.StopSubAllocator();
|
||||
}
|
||||
ppm.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,17 +59,20 @@ internal sealed partial class Unpack : BitInput
|
||||
ArrayPool<byte>.Shared.Return(Window);
|
||||
Window = null;
|
||||
}
|
||||
|
||||
FragWindow.Reset();
|
||||
if (FilterSrcMemory.Length != 0)
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(FilterSrcMemory);
|
||||
FilterSrcMemory = Array.Empty<byte>();
|
||||
}
|
||||
|
||||
if (FilterDstMemory.Length != 0)
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(FilterDstMemory);
|
||||
FilterDstMemory = Array.Empty<byte>();
|
||||
}
|
||||
|
||||
disposed = true;
|
||||
}
|
||||
|
||||
@@ -120,56 +123,70 @@ internal sealed partial class Unpack : BitInput
|
||||
throw new InvalidFormatException("Grow && Fragmented");
|
||||
}
|
||||
|
||||
var NewWindow = Fragmented ? null : ArrayPool<byte>.Shared.Rent((int)WinSize);
|
||||
|
||||
if (NewWindow == null)
|
||||
byte[] NewWindow = null;
|
||||
try
|
||||
{
|
||||
if (Grow || WinSize < 0x1000000)
|
||||
NewWindow = Fragmented ? null : ArrayPool<byte>.Shared.Rent((int)WinSize);
|
||||
|
||||
if (NewWindow == null)
|
||||
{
|
||||
// We do not support growth for new fragmented window.
|
||||
// Also exclude RAR4 and small dictionaries.
|
||||
//throw std::bad_alloc();
|
||||
throw new InvalidFormatException("Grow || WinSize<0x1000000");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Window != null) // If allocated by preceding files.
|
||||
if (Grow || WinSize < 0x1000000)
|
||||
{
|
||||
//free(Window);
|
||||
ArrayPool<byte>.Shared.Return(Window);
|
||||
Window = null;
|
||||
// We do not support growth for new fragmented window.
|
||||
// Also exclude RAR4 and small dictionaries.
|
||||
//throw std::bad_alloc();
|
||||
throw new InvalidFormatException("Grow || WinSize<0x1000000");
|
||||
}
|
||||
FragWindow.Init(WinSize);
|
||||
Fragmented = true;
|
||||
else
|
||||
{
|
||||
if (Window != null) // If allocated by preceding files.
|
||||
{
|
||||
//free(Window);
|
||||
ArrayPool<byte>.Shared.Return(Window);
|
||||
Window = null;
|
||||
}
|
||||
|
||||
FragWindow.Init(WinSize);
|
||||
Fragmented = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!Fragmented)
|
||||
{
|
||||
// Clean the window to generate the same output when unpacking corrupt
|
||||
// RAR files, which may access unused areas of sliding dictionary.
|
||||
// sharpcompress: don't need this, freshly allocated above
|
||||
//memset(NewWindow,0,WinSize);
|
||||
|
||||
// If Window is not NULL, it means that window size has grown.
|
||||
// In solid streams we need to copy data to a new window in such case.
|
||||
// RAR archiving code does not allow it in solid streams now,
|
||||
// but let's implement it anyway just in case we'll change it sometimes.
|
||||
if (Grow)
|
||||
{
|
||||
for (size_t I = 1; I <= MaxWinSize; I++)
|
||||
{
|
||||
NewWindow[(UnpPtr - I) & (WinSize - 1)] = Window[
|
||||
(UnpPtr - I) & (MaxWinSize - 1)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if (Window != null)
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(Window);
|
||||
}
|
||||
|
||||
Window = NewWindow;
|
||||
NewWindow = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (!Fragmented)
|
||||
finally
|
||||
{
|
||||
// Clean the window to generate the same output when unpacking corrupt
|
||||
// RAR files, which may access unused areas of sliding dictionary.
|
||||
// sharpcompress: don't need this, freshly allocated above
|
||||
//memset(NewWindow,0,WinSize);
|
||||
|
||||
// If Window is not NULL, it means that window size has grown.
|
||||
// In solid streams we need to copy data to a new window in such case.
|
||||
// RAR archiving code does not allow it in solid streams now,
|
||||
// but let's implement it anyway just in case we'll change it sometimes.
|
||||
if (Grow)
|
||||
if (NewWindow != null)
|
||||
{
|
||||
for (size_t I = 1; I <= MaxWinSize; I++)
|
||||
{
|
||||
NewWindow[(UnpPtr - I) & (WinSize - 1)] = Window[
|
||||
(UnpPtr - I) & (MaxWinSize - 1)
|
||||
];
|
||||
}
|
||||
ArrayPool<byte>.Shared.Return(NewWindow);
|
||||
}
|
||||
|
||||
if (Window != null)
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(Window);
|
||||
}
|
||||
Window = NewWindow;
|
||||
}
|
||||
|
||||
MaxWinSize = WinSize;
|
||||
@@ -279,6 +296,7 @@ internal sealed partial class Unpack : BitInput
|
||||
UnpPtr = WrPtr = 0;
|
||||
WriteBorder = Math.Min(MaxWinSize, UNPACK_MAX_WRITE) & MaxWinMask;
|
||||
}
|
||||
|
||||
// Filters never share several solid files, so we can safely reset them
|
||||
// even in solid archive.
|
||||
InitFilters();
|
||||
|
||||
@@ -321,9 +321,9 @@
|
||||
"net10.0": {
|
||||
"Microsoft.NET.ILLink.Tasks": {
|
||||
"type": "Direct",
|
||||
"requested": "[10.0.6, )",
|
||||
"resolved": "10.0.6",
|
||||
"contentHash": "QKuvS0LWX4fjFqeDkyM7Kqt8P3wYTiPD4nwU+9y59n0sCiG714fxDgbbN82vDnzq89AF/PiHl92TP2C4aFDUQA=="
|
||||
"requested": "[10.0.8, )",
|
||||
"resolved": "10.0.8",
|
||||
"contentHash": "dVbSXGIFNR5nZcv2tOLoWI+a9T4jtFd77IYjuND+QVe360qWgAF7H0WtoopYhRw/+SgpGUTyrkrh+65+ClNnfw=="
|
||||
},
|
||||
"Microsoft.NETFramework.ReferenceAssemblies": {
|
||||
"type": "Direct",
|
||||
@@ -441,9 +441,9 @@
|
||||
"net8.0": {
|
||||
"Microsoft.NET.ILLink.Tasks": {
|
||||
"type": "Direct",
|
||||
"requested": "[8.0.26, )",
|
||||
"resolved": "8.0.26",
|
||||
"contentHash": "o7/yVssM2r9Wyln2s9edBd5ANZXqdSdBI+g7JqXkyJmXrhs2WsJp25K5yPnYrTgdKBCjKB8bg+O2oew4sgzFaA=="
|
||||
"requested": "[8.0.27, )",
|
||||
"resolved": "8.0.27",
|
||||
"contentHash": "rQi9TxifHRnXP7lVRZH05DxD2/XGbJp12q0ozcbrlBlBnyyzssFTH/2vLhtKWUp2CT1qVscTrcYTFiwTyKPKRg=="
|
||||
},
|
||||
"Microsoft.NETFramework.ReferenceAssemblies": {
|
||||
"type": "Direct",
|
||||
|
||||
@@ -81,13 +81,13 @@ public class Program
|
||||
using (profiler)
|
||||
{
|
||||
// Run a simple benchmark iteration
|
||||
var zipBenchmark = new Benchmarks.SevenZipBenchmarks();
|
||||
var zipBenchmark = new Benchmarks.RarBenchmarks();
|
||||
zipBenchmark.Setup();
|
||||
|
||||
Console.WriteLine("Running benchmark iterations...");
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
await zipBenchmark.SevenZipLzma2ExtractAsync_Reader();
|
||||
await zipBenchmark.RarExtractArchiveApiAsync();
|
||||
if (i % 3 == 0)
|
||||
{
|
||||
Console.Write(".");
|
||||
|
||||
Reference in New Issue
Block a user