Now can download .pack.xz file for Forge library.
This commit is contained in:
134
HMCLAPI/src/main/java/org/tukaani/xz/BlockOutputStream.java
Normal file
134
HMCLAPI/src/main/java/org/tukaani/xz/BlockOutputStream.java
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* BlockOutputStream
|
||||
*
|
||||
* Author: Lasse Collin <lasse.collin@tukaani.org>
|
||||
*
|
||||
* This file has been put into the public domain.
|
||||
* You can do whatever you want with this file.
|
||||
*/
|
||||
|
||||
package org.tukaani.xz;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import org.tukaani.xz.common.EncoderUtil;
|
||||
import org.tukaani.xz.check.Check;
|
||||
|
||||
class BlockOutputStream extends FinishableOutputStream {
|
||||
private final OutputStream out;
|
||||
private final CountingOutputStream outCounted;
|
||||
private FinishableOutputStream filterChain;
|
||||
private final Check check;
|
||||
|
||||
private final int headerSize;
|
||||
private final long compressedSizeLimit;
|
||||
private long uncompressedSize = 0;
|
||||
|
||||
private final byte[] tempBuf = new byte[1];
|
||||
|
||||
public BlockOutputStream(OutputStream out, FilterEncoder[] filters,
|
||||
Check check) throws IOException {
|
||||
this.out = out;
|
||||
this.check = check;
|
||||
|
||||
// Initialize the filter chain.
|
||||
outCounted = new CountingOutputStream(out);
|
||||
filterChain = outCounted;
|
||||
for (int i = filters.length - 1; i >= 0; --i)
|
||||
filterChain = filters[i].getOutputStream(filterChain);
|
||||
|
||||
// Prepare to encode the Block Header field.
|
||||
ByteArrayOutputStream bufStream = new ByteArrayOutputStream();
|
||||
|
||||
// Write a dummy Block Header Size field. The real value is written
|
||||
// once everything else except CRC32 has been written.
|
||||
bufStream.write(0x00);
|
||||
|
||||
// Write Block Flags. Storing Compressed Size or Uncompressed Size
|
||||
// isn't supported for now.
|
||||
bufStream.write(filters.length - 1);
|
||||
|
||||
// List of Filter Flags
|
||||
for (int i = 0; i < filters.length; ++i) {
|
||||
EncoderUtil.encodeVLI(bufStream, filters[i].getFilterID());
|
||||
byte[] filterProps = filters[i].getFilterProps();
|
||||
EncoderUtil.encodeVLI(bufStream, filterProps.length);
|
||||
bufStream.write(filterProps);
|
||||
}
|
||||
|
||||
// Header Padding
|
||||
while ((bufStream.size() & 3) != 0)
|
||||
bufStream.write(0x00);
|
||||
|
||||
byte[] buf = bufStream.toByteArray();
|
||||
|
||||
// Total size of the Block Header: Take the size of the CRC32 field
|
||||
// into account.
|
||||
headerSize = buf.length + 4;
|
||||
|
||||
// This is just a sanity check.
|
||||
if (headerSize > EncoderUtil.BLOCK_HEADER_SIZE_MAX)
|
||||
throw new UnsupportedOptionsException();
|
||||
|
||||
// Block Header Size
|
||||
buf[0] = (byte)(buf.length / 4);
|
||||
|
||||
// Write the Block Header field to the output stream.
|
||||
out.write(buf);
|
||||
EncoderUtil.writeCRC32(out, buf);
|
||||
|
||||
// Calculate the maximum allowed size of the Compressed Data field.
|
||||
// It is hard to exceed it so this is mostly to be pedantic.
|
||||
compressedSizeLimit = (EncoderUtil.VLI_MAX & ~3)
|
||||
- headerSize - check.getSize();
|
||||
}
|
||||
|
||||
public void write(int b) throws IOException {
|
||||
tempBuf[0] = (byte)b;
|
||||
write(tempBuf, 0, 1);
|
||||
}
|
||||
|
||||
public void write(byte[] buf, int off, int len) throws IOException {
|
||||
filterChain.write(buf, off, len);
|
||||
check.update(buf, off, len);
|
||||
uncompressedSize += len;
|
||||
validate();
|
||||
}
|
||||
|
||||
public void flush() throws IOException {
|
||||
filterChain.flush();
|
||||
validate();
|
||||
}
|
||||
|
||||
public void finish() throws IOException {
|
||||
// Finish the Compressed Data field.
|
||||
filterChain.finish();
|
||||
validate();
|
||||
|
||||
// Block Padding
|
||||
for (long i = outCounted.getSize(); (i & 3) != 0; ++i)
|
||||
out.write(0x00);
|
||||
|
||||
// Check
|
||||
out.write(check.finish());
|
||||
}
|
||||
|
||||
private void validate() throws IOException {
|
||||
long compressedSize = outCounted.getSize();
|
||||
|
||||
// It is very hard to trigger this exception.
|
||||
// This is just to be pedantic.
|
||||
if (compressedSize < 0 || compressedSize > compressedSizeLimit
|
||||
|| uncompressedSize < 0)
|
||||
throw new XZIOException("XZ Stream has grown too big");
|
||||
}
|
||||
|
||||
public long getUnpaddedSize() {
|
||||
return headerSize + outCounted.getSize() + check.getSize();
|
||||
}
|
||||
|
||||
public long getUncompressedSize() {
|
||||
return uncompressedSize;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user