mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-09-22 15:04:43 +00:00
some AI changes
This commit is contained in:
@@ -333,6 +333,65 @@ internal class ModelPpm
|
||||
return (_minContext.Address != 0);
|
||||
}
|
||||
|
||||
internal async ValueTask<bool> DecodeInitAsync(
|
||||
IRarUnpack unpackRead,
|
||||
int escChar,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
var maxOrder =
|
||||
await unpackRead.ReadCharAsync(cancellationToken).ConfigureAwait(false) & 0xff;
|
||||
var reset = ((maxOrder & 0x20) != 0);
|
||||
|
||||
var maxMb = 0;
|
||||
if (reset)
|
||||
{
|
||||
maxMb = await unpackRead.ReadCharAsync(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (SubAlloc.GetAllocatedMemory() == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if ((maxOrder & 0x40) != 0)
|
||||
{
|
||||
escChar = await unpackRead.ReadCharAsync(cancellationToken).ConfigureAwait(false);
|
||||
unpackRead.PpmEscChar = escChar;
|
||||
}
|
||||
Coder = new RangeCoder();
|
||||
await Coder.InitAsync(unpackRead, cancellationToken).ConfigureAwait(false);
|
||||
if (reset)
|
||||
{
|
||||
maxOrder = (maxOrder & 0x1f) + 1;
|
||||
if (maxOrder > 16)
|
||||
{
|
||||
maxOrder = 16 + ((maxOrder - 16) * 3);
|
||||
}
|
||||
if (maxOrder == 1)
|
||||
{
|
||||
SubAlloc.StopSubAllocator();
|
||||
return false;
|
||||
}
|
||||
SubAlloc.StartSubAllocator((maxMb + 1) << 20);
|
||||
_minContext = 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;
|
||||
}
|
||||
|
||||
public virtual int DecodeChar()
|
||||
{
|
||||
// Debug
|
||||
|
||||
@@ -19,7 +19,7 @@ internal class RangeCoder
|
||||
private long _low,
|
||||
_code,
|
||||
_range;
|
||||
private readonly IRarUnpack _unpackRead;
|
||||
private IRarUnpack _unpackRead;
|
||||
private readonly Stream _stream;
|
||||
|
||||
internal RangeCoder(IRarUnpack unpackRead)
|
||||
@@ -36,6 +36,24 @@ internal class RangeCoder
|
||||
|
||||
internal RangeCoder() { }
|
||||
|
||||
internal async ValueTask InitAsync(
|
||||
IRarUnpack unpackRead,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
_unpackRead = unpackRead;
|
||||
SubRange = new SubRange();
|
||||
|
||||
_low = _code = 0L;
|
||||
_range = 0xFFFFffffL;
|
||||
for (var i = 0; i < 4; i++)
|
||||
{
|
||||
_code =
|
||||
((_code << 8) | await ReadCharAsync(cancellationToken).ConfigureAwait(false))
|
||||
& UINT_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
private void Init()
|
||||
{
|
||||
SubRange = new SubRange();
|
||||
@@ -131,7 +149,7 @@ internal class RangeCoder
|
||||
{
|
||||
if (_unpackRead != null)
|
||||
{
|
||||
return _unpackRead.Char;
|
||||
return await _unpackRead.ReadCharAsync(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
if (_stream != null)
|
||||
{
|
||||
|
||||
@@ -141,7 +141,7 @@ internal sealed partial class Unpack
|
||||
|
||||
if (((wrPtr - unpPtr) & PackDef.MAXWINMASK) < 260 && wrPtr != unpPtr)
|
||||
{
|
||||
UnpWriteBuf();
|
||||
await UnpWriteBufAsync(cancellationToken).ConfigureAwait(false);
|
||||
if (destUnpSize < 0)
|
||||
{
|
||||
return;
|
||||
@@ -154,7 +154,7 @@ internal sealed partial class Unpack
|
||||
}
|
||||
if (unpBlockType == BlockTypes.BLOCK_PPM)
|
||||
{
|
||||
var Ch = ppm.DecodeChar();
|
||||
var Ch = await ppm.DecodeCharAsync(cancellationToken).ConfigureAwait(false);
|
||||
if (Ch == -1)
|
||||
{
|
||||
ppmError = true;
|
||||
@@ -162,7 +162,7 @@ internal sealed partial class Unpack
|
||||
}
|
||||
if (Ch == PpmEscChar)
|
||||
{
|
||||
var NextCh = ppm.DecodeChar();
|
||||
var NextCh = await ppm.DecodeCharAsync(cancellationToken).ConfigureAwait(false);
|
||||
if (NextCh == 0)
|
||||
{
|
||||
if (!await ReadTablesAsync(cancellationToken).ConfigureAwait(false))
|
||||
@@ -177,7 +177,7 @@ internal sealed partial class Unpack
|
||||
}
|
||||
if (NextCh == 3)
|
||||
{
|
||||
if (!ReadVMCodePPM())
|
||||
if (!await ReadVMCodePPMAsync(cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -190,7 +190,8 @@ internal sealed partial class Unpack
|
||||
var failed = false;
|
||||
for (var I = 0; I < 4 && !failed; I++)
|
||||
{
|
||||
var ch = ppm.DecodeChar();
|
||||
var ch = await ppm.DecodeCharAsync(cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
if (ch == -1)
|
||||
{
|
||||
failed = true;
|
||||
@@ -216,7 +217,8 @@ internal sealed partial class Unpack
|
||||
}
|
||||
if (NextCh == 5)
|
||||
{
|
||||
var Length = ppm.DecodeChar();
|
||||
var Length = await ppm.DecodeCharAsync(cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
if (Length == -1)
|
||||
{
|
||||
break;
|
||||
@@ -354,7 +356,7 @@ internal sealed partial class Unpack
|
||||
CopyString(2, Distance);
|
||||
}
|
||||
}
|
||||
UnpWriteBuf();
|
||||
await UnpWriteBufAsync(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task UnpWriteBufAsync(CancellationToken cancellationToken = default)
|
||||
@@ -622,7 +624,8 @@ internal sealed partial class Unpack
|
||||
if ((bitField & 0x8000) != 0)
|
||||
{
|
||||
unpBlockType = BlockTypes.BLOCK_PPM;
|
||||
return ppm.DecodeInit(this, PpmEscChar);
|
||||
return await ppm.DecodeInitAsync(this, PpmEscChar, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
unpBlockType = BlockTypes.BLOCK_LZ;
|
||||
|
||||
@@ -793,4 +796,58 @@ internal sealed partial class Unpack
|
||||
}
|
||||
return AddVMCode(FirstByte, vmCode);
|
||||
}
|
||||
|
||||
public async ValueTask<int> ReadCharAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (inAddr > MAX_SIZE - 30)
|
||||
{
|
||||
await unpReadBufAsync(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
return InBuf[inAddr++] & 0xff;
|
||||
}
|
||||
|
||||
private async Task<bool> ReadVMCodePPMAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
var FirstByte = await ppm.DecodeCharAsync(cancellationToken).ConfigureAwait(false);
|
||||
if (FirstByte == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var Length = (FirstByte & 7) + 1;
|
||||
if (Length == 7)
|
||||
{
|
||||
var B1 = await ppm.DecodeCharAsync(cancellationToken).ConfigureAwait(false);
|
||||
if (B1 == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Length = B1 + 7;
|
||||
}
|
||||
else if (Length == 8)
|
||||
{
|
||||
var B1 = await ppm.DecodeCharAsync(cancellationToken).ConfigureAwait(false);
|
||||
if (B1 == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var B2 = await ppm.DecodeCharAsync(cancellationToken).ConfigureAwait(false);
|
||||
if (B2 == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Length = (B1 * 256) + B2;
|
||||
}
|
||||
|
||||
var vmCode = new List<byte>();
|
||||
for (var I = 0; I < Length; I++)
|
||||
{
|
||||
var Ch = await ppm.DecodeCharAsync(cancellationToken).ConfigureAwait(false);
|
||||
if (Ch == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
vmCode.Add((byte)Ch);
|
||||
}
|
||||
return AddVMCode(FirstByte, vmCode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ internal partial class Unpack
|
||||
}
|
||||
if (((wrPtr - unpPtr) & PackDef.MAXWINMASK) < 270 && wrPtr != unpPtr)
|
||||
{
|
||||
oldUnpWriteBuf();
|
||||
await oldUnpWriteBufAsync(cancellationToken).ConfigureAwait(false);
|
||||
if (suspended)
|
||||
{
|
||||
return;
|
||||
@@ -105,7 +105,7 @@ internal partial class Unpack
|
||||
}
|
||||
}
|
||||
}
|
||||
oldUnpWriteBuf();
|
||||
await oldUnpWriteBufAsync(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task<bool> unpReadBufAsync(CancellationToken cancellationToken = default)
|
||||
|
||||
@@ -45,7 +45,7 @@ internal partial class Unpack
|
||||
}
|
||||
if (((wrPtr - unpPtr) & PackDef.MAXWINMASK) < 270 && wrPtr != unpPtr)
|
||||
{
|
||||
oldUnpWriteBuf();
|
||||
await oldUnpWriteBufAsync(cancellationToken).ConfigureAwait(false);
|
||||
if (suspended)
|
||||
{
|
||||
return;
|
||||
@@ -157,8 +157,8 @@ internal partial class Unpack
|
||||
CopyString20(2, Distance);
|
||||
}
|
||||
}
|
||||
ReadLastTables();
|
||||
oldUnpWriteBuf();
|
||||
await ReadLastTablesAsync(cancellationToken).ConfigureAwait(false);
|
||||
await oldUnpWriteBufAsync(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task<bool> ReadTables20Async(CancellationToken cancellationToken = default)
|
||||
@@ -272,4 +272,25 @@ internal partial class Unpack
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task ReadLastTablesAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (readTop >= inAddr + 5)
|
||||
{
|
||||
if (UnpAudioBlock != 0)
|
||||
{
|
||||
if (this.decodeNumber(MD[UnpCurChannel]) == 256)
|
||||
{
|
||||
await ReadTables20Async(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.decodeNumber(LD) == 269)
|
||||
{
|
||||
await ReadTables20Async(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ internal partial class Unpack
|
||||
&& WriteBorder != UnpPtr
|
||||
)
|
||||
{
|
||||
UnpWriteBuf();
|
||||
await UnpWriteBufAsync(cancellationToken).ConfigureAwait(false);
|
||||
if (WrittenFileSize > DestUnpSize)
|
||||
{
|
||||
return;
|
||||
@@ -197,7 +197,7 @@ internal partial class Unpack
|
||||
var Filter = new UnpackFilter();
|
||||
if (
|
||||
!await ReadFilterAsync(Filter, cancellationToken).ConfigureAwait(false)
|
||||
|| !AddFilter(Filter)
|
||||
|| !await AddFilterAsync(Filter, cancellationToken).ConfigureAwait(false)
|
||||
)
|
||||
{
|
||||
break;
|
||||
@@ -232,7 +232,7 @@ internal partial class Unpack
|
||||
continue;
|
||||
}
|
||||
}
|
||||
UnpWriteBuf();
|
||||
await UnpWriteBufAsync(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task<bool> ReadBlockHeaderAsync(CancellationToken cancellationToken = default)
|
||||
@@ -318,4 +318,24 @@ internal partial class Unpack
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task<bool> AddFilterAsync(
|
||||
UnpackFilter Filter,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
if (Filters.Count >= MAX_UNPACK_FILTERS)
|
||||
{
|
||||
await UnpWriteBufAsync(cancellationToken).ConfigureAwait(false);
|
||||
if (Filters.Count >= MAX_UNPACK_FILTERS)
|
||||
{
|
||||
InitFilters();
|
||||
}
|
||||
}
|
||||
|
||||
Filter.NextWindow = WrPtr != UnpPtr && ((WrPtr - UnpPtr) & MaxWinMask) <= Filter.BlockStart;
|
||||
Filter.uBlockStart = (uint)((Filter.BlockStart + UnpPtr) & MaxWinMask);
|
||||
Filters.Add(Filter);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,30 @@ namespace SharpCompress.Test.Rar;
|
||||
|
||||
public class RarReaderAsyncTests : ReaderTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("Rar15.rar")]
|
||||
[InlineData("Rar.rar")]
|
||||
[InlineData("Rar.Audio_program.rar")]
|
||||
[InlineData("Rar5.rar")]
|
||||
[InlineData("Rar5.solid.rar")]
|
||||
public async ValueTask Rar_Reader_Async_Uses_Only_Async_Stream_Operations(string filename)
|
||||
{
|
||||
using var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, filename));
|
||||
await using var reader = await ReaderFactory.OpenAsyncReader(
|
||||
new AsyncOnlyStream(stream),
|
||||
new ReaderOptions { LookForHeader = true }
|
||||
);
|
||||
|
||||
while (await reader.MoveToNextEntryAsync())
|
||||
{
|
||||
if (!reader.Entry.IsDirectory)
|
||||
{
|
||||
using var output = new SyncWriteNotSupportedStream(new MemoryStream());
|
||||
await reader.WriteEntryToAsync(output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async ValueTask Rar_Multi_Reader_Async() =>
|
||||
await DoRar_Multi_Reader_Async([
|
||||
@@ -371,4 +395,56 @@ public class RarReaderAsyncTests : ReaderTests
|
||||
}
|
||||
VerifyFiles();
|
||||
}
|
||||
|
||||
private sealed class SyncWriteNotSupportedStream(Stream stream) : Stream
|
||||
{
|
||||
public override bool CanRead => stream.CanRead;
|
||||
|
||||
public override bool CanSeek => stream.CanSeek;
|
||||
|
||||
public override bool CanWrite => stream.CanWrite;
|
||||
|
||||
public override long Length => stream.Length;
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get => stream.Position;
|
||||
set => stream.Position = value;
|
||||
}
|
||||
|
||||
public override void Flush() => stream.Flush();
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count) =>
|
||||
stream.Read(buffer, offset, count);
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin) => stream.Seek(offset, origin);
|
||||
|
||||
public override void SetLength(long value) => stream.SetLength(value);
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count) =>
|
||||
throw new NotSupportedException("Synchronous Write is not supported");
|
||||
|
||||
public override Task WriteAsync(
|
||||
byte[] buffer,
|
||||
int offset,
|
||||
int count,
|
||||
System.Threading.CancellationToken cancellationToken
|
||||
) => stream.WriteAsync(buffer, offset, count, cancellationToken);
|
||||
|
||||
#if NET8_0_OR_GREATER
|
||||
public override ValueTask WriteAsync(
|
||||
ReadOnlyMemory<byte> buffer,
|
||||
System.Threading.CancellationToken cancellationToken = default
|
||||
) => stream.WriteAsync(buffer, cancellationToken);
|
||||
#endif
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
stream.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user