use of net.contrapunctus.lzma.LzmaInputStream in project disunity by ata4.
the class BundleReader method read.
public Bundle read() throws BundleException, IOException {
bundle = new Bundle();
in.position(0);
BundleHeader header = bundle.header();
in.readStruct(header);
// check signature
if (!header.hasValidSignature()) {
throw new BundleException("Invalid signature");
}
List<BundleEntryInfo> entryInfos = bundle.entryInfos();
if (header.compressedDataHeaderSize() > 0) {
if (header.dataHeaderAtEndOfFile()) {
in.position(header.completeFileSize() - header.compressedDataHeaderSize());
}
// build an input stream for the uncompressed data header
InputStream headerIn = new BoundedInputStream(in.stream(), header.compressedDataHeaderSize());
DataReader inData;
switch(header.dataHeaderCompressionScheme()) {
default:
case 0:
// Not compressed
inData = DataReaders.forInputStream(headerIn);
case 1:
// LZMA
inData = DataReaders.forInputStream(new CountingInputStream(new LzmaInputStream(headerIn)));
case 3:
// LZ4
byte[] compressed = new byte[header.compressedDataHeaderSize()];
byte[] decompressed = new byte[(int) header.dataHeaderSize()];
headerIn.read(compressed);
LZ4JavaSafeFastDecompressor.INSTANCE.decompress(compressed, decompressed);
inData = DataReaders.forByteBuffer(ByteBuffer.wrap(decompressed));
}
// Block info: not captured for now
{
// 16 bytes unknown
byte[] unknown = new byte[16];
inData.readBytes(unknown);
int storageBlocks = inData.readInt();
for (int i = 0; i < storageBlocks; ++i) {
inData.readUnsignedInt();
inData.readUnsignedInt();
inData.readUnsignedShort();
}
}
int files = inData.readInt();
for (int i = 0; i < files; i++) {
BundleEntryInfo entryInfo = new BundleEntryInfoFS();
inData.readStruct(entryInfo);
entryInfos.add(entryInfo);
}
} else {
// raw or web header
long dataHeaderSize = header.dataHeaderSize();
if (dataHeaderSize == 0) {
// old stream versions don't store the data header size, so use a large
// fixed number instead
dataHeaderSize = 4096;
}
InputStream is = dataInputStream(0, dataHeaderSize);
DataReader inData = DataReaders.forInputStream(is);
int files = inData.readInt();
for (int i = 0; i < files; i++) {
BundleEntryInfo entryInfo = new BundleEntryInfo();
inData.readStruct(entryInfo);
entryInfos.add(entryInfo);
}
}
// sort entries by offset so that they're in the order in which they
// appear in the file, which is convenient for compressed bundles
entryInfos.sort((a, b) -> Long.compare(a.offset(), b.offset()));
List<BundleEntry> entries = bundle.entries();
entryInfos.forEach(entryInfo -> {
entries.add(new BundleInternalEntry(entryInfo, this::inputStreamForEntry));
});
return bundle;
}
use of net.contrapunctus.lzma.LzmaInputStream in project disunity by ata4.
the class BundleReader method dataInputStream.
private InputStream dataInputStream(long offset, long size) throws IOException {
InputStream is;
// use LZMA stream if the bundle is compressed
if (bundle.header().compressed()) {
// create initial input stream if required
if (lzma == null) {
lzma = lzmaInputStream();
}
// recreate stream if the offset is behind
long lzmaOffset = lzma.getByteCount();
if (lzmaOffset > offset) {
lzma.close();
lzma = lzmaInputStream();
}
// skip forward if required
if (lzmaOffset < offset) {
lzma.skip(offset - lzmaOffset);
}
is = lzma;
} else {
in.position(bundle.header().headerSize() + offset);
is = in.stream();
}
return new BoundedInputStream(is, size);
}
Aggregations