commit
e14ed89f3d
15 changed files with 350 additions and 0 deletions
49
src/SharpCompress/Compressors/Filters/BCJFilterARM.cs
Normal file
49
src/SharpCompress/Compressors/Filters/BCJFilterARM.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
47
src/SharpCompress/Compressors/Filters/BCJFilterARMT.cs
Normal file
47
src/SharpCompress/Compressors/Filters/BCJFilterARMT.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
107
src/SharpCompress/Compressors/Filters/BCJFilterIA64.cs
Normal file
107
src/SharpCompress/Compressors/Filters/BCJFilterIA64.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
48
src/SharpCompress/Compressors/Filters/BCJFilterPPC.cs
Normal file
48
src/SharpCompress/Compressors/Filters/BCJFilterPPC.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
58
src/SharpCompress/Compressors/Filters/BCJFilterSPARC.cs
Normal file
58
src/SharpCompress/Compressors/Filters/BCJFilterSPARC.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
BIN
tests/TestArchives/Archives/7Zip.ARM.7z
Normal file
BIN
tests/TestArchives/Archives/7Zip.ARM.7z
Normal file
Binary file not shown.
BIN
tests/TestArchives/Archives/7Zip.ARMT.7z
Normal file
BIN
tests/TestArchives/Archives/7Zip.ARMT.7z
Normal file
Binary file not shown.
BIN
tests/TestArchives/Archives/7Zip.BCJ.7z
Normal file
BIN
tests/TestArchives/Archives/7Zip.BCJ.7z
Normal file
Binary file not shown.
BIN
tests/TestArchives/Archives/7Zip.BCJ2.7z
Normal file
BIN
tests/TestArchives/Archives/7Zip.BCJ2.7z
Normal file
Binary file not shown.
BIN
tests/TestArchives/Archives/7Zip.Filters.7z
Normal file
BIN
tests/TestArchives/Archives/7Zip.Filters.7z
Normal file
Binary file not shown.
BIN
tests/TestArchives/Archives/7Zip.IA64.7z
Normal file
BIN
tests/TestArchives/Archives/7Zip.IA64.7z
Normal file
Binary file not shown.
BIN
tests/TestArchives/Archives/7Zip.PPC.7z
Normal file
BIN
tests/TestArchives/Archives/7Zip.PPC.7z
Normal file
Binary file not shown.
BIN
tests/TestArchives/Archives/7Zip.SPARC.7z
Normal file
BIN
tests/TestArchives/Archives/7Zip.SPARC.7z
Normal file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue