Komplettes G-Earth Paket inkl. JRE, Extensions und Tools. Extensions: - G-BuildTools, G-Click Ultimate, G-Loader, G-Manipulate - G-Presets, G-Translator, G-Trigger, G-itemViewer - Market Utils, Packet Info Explorer, Plants - RandomRoomVisitor, RoomLogger, Sanbovir Photo Inspector - SpyFriends, WallAligner, XabboScripter, xabbo
161 lines
5.0 KiB
Java
161 lines
5.0 KiB
Java
/*
|
|
* Decompiled with CFR 0.152.
|
|
*/
|
|
package okio;
|
|
|
|
import java.io.EOFException;
|
|
import java.io.IOException;
|
|
import java.util.zip.CRC32;
|
|
import java.util.zip.Inflater;
|
|
import okio.Buffer;
|
|
import okio.BufferedSource;
|
|
import okio.InflaterSource;
|
|
import okio.Okio;
|
|
import okio.Segment;
|
|
import okio.Source;
|
|
import okio.Timeout;
|
|
|
|
public final class GzipSource
|
|
implements Source {
|
|
private static final byte FHCRC = 1;
|
|
private static final byte FEXTRA = 2;
|
|
private static final byte FNAME = 3;
|
|
private static final byte FCOMMENT = 4;
|
|
private static final byte SECTION_HEADER = 0;
|
|
private static final byte SECTION_BODY = 1;
|
|
private static final byte SECTION_TRAILER = 2;
|
|
private static final byte SECTION_DONE = 3;
|
|
private int section = 0;
|
|
private final BufferedSource source;
|
|
private final Inflater inflater;
|
|
private final InflaterSource inflaterSource;
|
|
private final CRC32 crc = new CRC32();
|
|
|
|
public GzipSource(Source source) {
|
|
if (source == null) {
|
|
throw new IllegalArgumentException("source == null");
|
|
}
|
|
this.inflater = new Inflater(true);
|
|
this.source = Okio.buffer(source);
|
|
this.inflaterSource = new InflaterSource(this.source, this.inflater);
|
|
}
|
|
|
|
@Override
|
|
public long read(Buffer sink, long byteCount) throws IOException {
|
|
if (byteCount < 0L) {
|
|
throw new IllegalArgumentException("byteCount < 0: " + byteCount);
|
|
}
|
|
if (byteCount == 0L) {
|
|
return 0L;
|
|
}
|
|
if (this.section == 0) {
|
|
this.consumeHeader();
|
|
this.section = 1;
|
|
}
|
|
if (this.section == 1) {
|
|
long offset = sink.size;
|
|
long result = this.inflaterSource.read(sink, byteCount);
|
|
if (result != -1L) {
|
|
this.updateCrc(sink, offset, result);
|
|
return result;
|
|
}
|
|
this.section = 2;
|
|
}
|
|
if (this.section == 2) {
|
|
this.consumeTrailer();
|
|
this.section = 3;
|
|
if (!this.source.exhausted()) {
|
|
throw new IOException("gzip finished without exhausting source");
|
|
}
|
|
}
|
|
return -1L;
|
|
}
|
|
|
|
private void consumeHeader() throws IOException {
|
|
boolean fhcrc;
|
|
this.source.require(10L);
|
|
byte flags = this.source.buffer().getByte(3L);
|
|
boolean bl = fhcrc = (flags >> 1 & 1) == 1;
|
|
if (fhcrc) {
|
|
this.updateCrc(this.source.buffer(), 0L, 10L);
|
|
}
|
|
short id1id2 = this.source.readShort();
|
|
this.checkEqual("ID1ID2", 8075, id1id2);
|
|
this.source.skip(8L);
|
|
if ((flags >> 2 & 1) == 1) {
|
|
this.source.require(2L);
|
|
if (fhcrc) {
|
|
this.updateCrc(this.source.buffer(), 0L, 2L);
|
|
}
|
|
short xlen = this.source.buffer().readShortLe();
|
|
this.source.require(xlen);
|
|
if (fhcrc) {
|
|
this.updateCrc(this.source.buffer(), 0L, xlen);
|
|
}
|
|
this.source.skip(xlen);
|
|
}
|
|
if ((flags >> 3 & 1) == 1) {
|
|
long index = this.source.indexOf((byte)0);
|
|
if (index == -1L) {
|
|
throw new EOFException();
|
|
}
|
|
if (fhcrc) {
|
|
this.updateCrc(this.source.buffer(), 0L, index + 1L);
|
|
}
|
|
this.source.skip(index + 1L);
|
|
}
|
|
if ((flags >> 4 & 1) == 1) {
|
|
long index = this.source.indexOf((byte)0);
|
|
if (index == -1L) {
|
|
throw new EOFException();
|
|
}
|
|
if (fhcrc) {
|
|
this.updateCrc(this.source.buffer(), 0L, index + 1L);
|
|
}
|
|
this.source.skip(index + 1L);
|
|
}
|
|
if (fhcrc) {
|
|
this.checkEqual("FHCRC", this.source.readShortLe(), (short)this.crc.getValue());
|
|
this.crc.reset();
|
|
}
|
|
}
|
|
|
|
private void consumeTrailer() throws IOException {
|
|
this.checkEqual("CRC", this.source.readIntLe(), (int)this.crc.getValue());
|
|
this.checkEqual("ISIZE", this.source.readIntLe(), this.inflater.getTotalOut());
|
|
}
|
|
|
|
@Override
|
|
public Timeout timeout() {
|
|
return this.source.timeout();
|
|
}
|
|
|
|
@Override
|
|
public void close() throws IOException {
|
|
this.inflaterSource.close();
|
|
}
|
|
|
|
private void updateCrc(Buffer buffer, long offset, long byteCount) {
|
|
Segment s = buffer.head;
|
|
while (offset >= (long)(s.limit - s.pos)) {
|
|
offset -= (long)(s.limit - s.pos);
|
|
s = s.next;
|
|
}
|
|
while (byteCount > 0L) {
|
|
int pos = (int)((long)s.pos + offset);
|
|
int toUpdate = (int)Math.min((long)(s.limit - pos), byteCount);
|
|
this.crc.update(s.data, pos, toUpdate);
|
|
byteCount -= (long)toUpdate;
|
|
offset = 0L;
|
|
s = s.next;
|
|
}
|
|
}
|
|
|
|
private void checkEqual(String name, int expected, int actual) throws IOException {
|
|
if (actual != expected) {
|
|
throw new IOException(String.format("%s: actual 0x%08x != expected 0x%08x", name, actual, expected));
|
|
}
|
|
}
|
|
}
|
|
|