Merge pull request #759 from Erior/feature/748

Feature/748
This commit is contained in:
Adam Hathcock 2023-09-14 09:05:48 +01:00 committed by GitHub
commit e14ed89f3d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 350 additions and 0 deletions

View file

@ -0,0 +1,49 @@
using System.IO;
namespace SharpCompress.Compressors.Filters;
internal class BCJFilterARM : Filter
{
private int _pos;
public BCJFilterARM(bool isEncoder, Stream baseStream)
: base(isEncoder, baseStream, 8) => _pos = 8;
protected override int Transform(byte[] buffer, int offset, int count)
{
var end = offset + count - 4;
int i;
for (i = offset; i <= end; i += 4)
{
if ((buffer[i + 3] & 0xFF) == 0xEB)
{
int src =
((buffer[i + 2] & 0xFF) << 16)
| ((buffer[i + 1] & 0xFF) << 8)
| (buffer[i] & 0xFF);
src <<= 2;
int dest;
if (_isEncoder)
{
dest = src + (_pos + i - offset);
}
else
{
dest = src - (_pos + i - offset);
}
dest >>>= 2;
buffer[i + 2] = (byte)(dest >>> 16);
buffer[i + 1] = (byte)(dest >>> 8);
buffer[i] = (byte)dest;
}
}
i -= offset;
_pos += i;
return i;
}
}

View file

@ -0,0 +1,47 @@
using System.IO;
namespace SharpCompress.Compressors.Filters;
internal class BCJFilterARMT : Filter
{
private int _pos;
public BCJFilterARMT(bool isEncoder, Stream baseStream)
: base(isEncoder, baseStream, 4) => _pos = 4;
protected override int Transform(byte[] buffer, int offset, int count)
{
var end = offset + count - 4;
int i;
for (i = offset; i <= end; i += 2)
{
if ((buffer[i + 1] & 0xF8) == 0xF0 && (buffer[i + 3] & 0xF8) == 0xF8)
{
int src =
((buffer[i + 1] & 0x07) << 19)
| ((buffer[i] & 0xFF) << 11)
| ((buffer[i + 3] & 0x07) << 8)
| (buffer[i + 2] & 0xFF);
src <<= 1;
int dest;
if (_isEncoder)
dest = src + (_pos + i - offset);
else
dest = src - (_pos + i - offset);
dest >>>= 1;
buffer[i + 1] = (byte)(0xF0 | ((dest >>> 19) & 0x07));
buffer[i] = (byte)(dest >>> 11);
buffer[i + 3] = (byte)(0xF8 | ((dest >>> 8) & 0x07));
buffer[i + 2] = (byte)dest;
i += 2;
}
}
i -= offset;
_pos += i;
return i;
}
}

View file

@ -0,0 +1,107 @@
using System.IO;
namespace SharpCompress.Compressors.Filters;
internal class BCJFilterIA64 : Filter
{
private int _pos;
private static readonly int[] BRANCH_TABLE =
{
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
4,
4,
6,
6,
0,
0,
7,
7,
4,
4,
0,
0,
4,
4,
0,
0
};
public BCJFilterIA64(bool isEncoder, Stream baseStream)
: base(isEncoder, baseStream, 16) => _pos = 0;
protected override int Transform(byte[] buffer, int offset, int count)
{
var end = offset + count - 16;
int i;
for (i = offset; i <= end; i += 16)
{
int instrTemplate = buffer[i] & 0x1F;
int mask = BRANCH_TABLE[instrTemplate];
for (int slot = 0, bitPos = 5; slot < 3; ++slot, bitPos += 41)
{
if (((mask >>> slot) & 1) == 0)
continue;
int bytePos = bitPos >>> 3;
int bitRes = bitPos & 7;
long instr = 0;
for (int j = 0; j < 6; ++j)
{
instr |= (buffer[i + bytePos + j] & 0xFFL) << (8 * j);
}
long instrNorm = instr >>> bitRes;
if (((instrNorm >>> 37) & 0x0F) != 0x05 || ((instrNorm >>> 9) & 0x07) != 0x00)
continue;
int src = (int)((instrNorm >>> 13) & 0x0FFFFF);
src |= ((int)(instrNorm >>> 36) & 1) << 20;
src <<= 4;
int dest;
if (_isEncoder)
dest = src + (_pos + i - offset);
else
dest = src - (_pos + i - offset);
dest >>>= 4;
instrNorm &= ~(0x8FFFFFL << 13);
instrNorm |= (dest & 0x0FFFFFL) << 13;
instrNorm |= (dest & 0x100000L) << (36 - 20);
instr &= (1 << bitRes) - 1;
instr |= instrNorm << bitRes;
for (int j = 0; j < 6; ++j)
{
buffer[i + bytePos + j] = (byte)(instr >>> (8 * j));
}
}
}
i -= offset;
_pos += i;
return i;
}
}

View file

@ -0,0 +1,48 @@
using System.IO;
namespace SharpCompress.Compressors.Filters;
internal class BCJFilterPPC : Filter
{
private int _pos;
public BCJFilterPPC(bool isEncoder, Stream baseStream)
: base(isEncoder, baseStream, 4) => _pos = 0;
protected override int Transform(byte[] buffer, int offset, int count)
{
var end = offset + count - 4;
int i;
for (i = offset; i <= end; i += 4)
{
if ((buffer[i] & 0xFC) == 0x48 && (buffer[i + 3] & 0x03) == 0x01)
{
int src =
((buffer[i] & 0x03) << 24)
| ((buffer[i + 1] & 0xFF) << 16)
| ((buffer[i + 2] & 0xFF) << 8)
| (buffer[i + 3] & 0xFC);
int dest;
if (_isEncoder)
{
dest = src + (_pos + i - offset);
}
else
{
dest = src - (_pos + i - offset);
}
buffer[i] = (byte)(0x48 | ((dest >>> 24) & 0x03));
buffer[i + 1] = (byte)(dest >>> 16);
buffer[i + 2] = (byte)(dest >>> 8);
buffer[i + 3] = (byte)((buffer[i + 3] & 0x03) | dest);
}
}
i -= offset;
_pos += i;
return i;
}
}

View file

@ -0,0 +1,58 @@
using System.IO;
namespace SharpCompress.Compressors.Filters;
internal class BCJFilterSPARC : Filter
{
private int _pos;
public BCJFilterSPARC(bool isEncoder, Stream baseStream)
: base(isEncoder, baseStream, 4) => _pos = 0;
protected override int Transform(byte[] buffer, int offset, int count)
{
var end = offset + count - 4;
int i;
for (i = offset; i <= end; i += 4)
{
if (
(buffer[i] == 0x40 && (buffer[i + 1] & 0xC0) == 0x00)
|| (buffer[i] == 0x7F && (buffer[i + 1] & 0xC0) == 0xC0)
)
{
int src =
((buffer[i] & 0xFF) << 24)
| ((buffer[i + 1] & 0xFF) << 16)
| ((buffer[i + 2] & 0xFF) << 8)
| (buffer[i + 3] & 0xFF);
src <<= 2;
int dest;
if (_isEncoder)
{
dest = src + (_pos + i - offset);
}
else
{
dest = src - (_pos + i - offset);
}
dest >>>= 2;
dest =
(((0 - ((dest >>> 22) & 1)) << 22) & 0x3FFFFFFF)
| (dest & 0x3FFFFF)
| 0x40000000;
buffer[i] = (byte)(dest >>> 24);
buffer[i + 1] = (byte)(dest >>> 16);
buffer[i + 2] = (byte)(dest >>> 8);
buffer[i + 3] = (byte)dest;
}
}
i -= offset;
_pos += i;
return i;
}
}

View file

@ -20,6 +20,11 @@ internal static class DecoderRegistry
private const uint K_PPMD = 0x030401;
private const uint K_BCJ = 0x03030103;
private const uint K_BCJ2 = 0x0303011B;
private const uint K_PPC = 0x03030205;
private const uint K_IA64 = 0x03030401;
private const uint K_ARM = 0x03030501;
private const uint K_ARMT = 0x03030701;
private const uint K_SPARC = 0x03030805;
private const uint K_DEFLATE = 0x040108;
private const uint K_B_ZIP2 = 0x040202;
private const uint K_ZSTD = 0x4F71101;
@ -51,6 +56,16 @@ internal static class DecoderRegistry
return new BCJFilter(false, inStreams.Single());
case K_BCJ2:
return new Bcj2DecoderStream(inStreams, info, limit);
case K_PPC:
return new BCJFilterPPC(false, inStreams.Single());
case K_IA64:
return new BCJFilterIA64(false, inStreams.Single());
case K_ARM:
return new BCJFilterARM(false, inStreams.Single());
case K_ARMT:
return new BCJFilterARMT(false, inStreams.Single());
case K_SPARC:
return new BCJFilterSPARC(false, inStreams.Single());
case K_B_ZIP2:
return new BZip2Stream(inStreams.Single(), CompressionMode.Decompress, true);
case K_PPMD:

View file

@ -1,5 +1,6 @@
using System;
using System.IO;
using System.Linq;
using SharpCompress.Common;
using SharpCompress.Readers;
using Xunit;
@ -132,8 +133,33 @@ public class SevenZipArchiveTests : ArchiveTests
)
);
[Fact]
public void SevenZipArchive_Delta_FileRead() => ArchiveFileRead("7Zip.delta.7z");
[Fact]
public void SevenZipArchive_ARM_FileRead() => ArchiveFileRead("7Zip.ARM.7z");
[Fact]
public void SevenZipArchive_ARMT_FileRead() => ArchiveFileRead("7Zip.ARMT.7z");
[Fact]
public void SevenZipArchive_BCJ_FileRead() => ArchiveFileRead("7Zip.BCJ.7z");
[Fact]
public void SevenZipArchive_BCJ2_FileRead() => ArchiveFileRead("7Zip.BCJ2.7z");
[Fact]
public void SevenZipArchive_IA64_FileRead() => ArchiveFileRead("7Zip.IA64.7z");
[Fact]
public void SevenZipArchive_PPC_FileRead() => ArchiveFileRead("7Zip.PPC.7z");
[Fact]
public void SevenZipArchive_SPARC_FileRead() => ArchiveFileRead("7Zip.SPARC.7z");
[Fact]
public void SevenZipArchive_Filters_FileRead() => ArchiveFileRead("7Zip.Filters.7z");
[Fact]
public void SevenZipArchive_Delta_Distance() =>
ArchiveDeltaDistanceRead("7Zip.delta.distance.7z");

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.