some AI changes

This commit is contained in:
Adam Hathcock
2026-04-28 08:32:44 +01:00
parent 2d4d9c285a
commit 896dfd6537
7 changed files with 269 additions and 18 deletions

View File

@@ -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

View File

@@ -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)
{

View File

@@ -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);
}
}

View File

@@ -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)

View File

@@ -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);
}
}
}
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}
}