G-Earth/Extensions/G-Translator_1.0.2/decompiled/okio/Buffer.java
Administrator 368b92d87a G-Earth 1.5.4 beta 22 - Initial release
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
2026-03-16 09:45:04 +01:00

1326 lines
41 KiB
Java

/*
* Decompiled with CFR 0.152.
*/
package okio;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import okio.BufferedSink;
import okio.BufferedSource;
import okio.ByteString;
import okio.Segment;
import okio.SegmentPool;
import okio.SegmentedByteString;
import okio.Sink;
import okio.Source;
import okio.Timeout;
import okio.Util;
public final class Buffer
implements BufferedSource,
BufferedSink,
Cloneable {
private static final byte[] DIGITS = new byte[]{48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102};
static final int REPLACEMENT_CHARACTER = 65533;
Segment head;
long size;
public long size() {
return this.size;
}
@Override
public Buffer buffer() {
return this;
}
@Override
public OutputStream outputStream() {
return new OutputStream(){
@Override
public void write(int b) {
Buffer.this.writeByte((byte)b);
}
@Override
public void write(byte[] data, int offset, int byteCount) {
Buffer.this.write(data, offset, byteCount);
}
@Override
public void flush() {
}
@Override
public void close() {
}
public String toString() {
return this + ".outputStream()";
}
};
}
@Override
public Buffer emitCompleteSegments() {
return this;
}
@Override
public BufferedSink emit() {
return this;
}
@Override
public boolean exhausted() {
return this.size == 0L;
}
@Override
public void require(long byteCount) throws EOFException {
if (this.size < byteCount) {
throw new EOFException();
}
}
@Override
public boolean request(long byteCount) {
return this.size >= byteCount;
}
@Override
public InputStream inputStream() {
return new InputStream(){
@Override
public int read() {
if (Buffer.this.size > 0L) {
return Buffer.this.readByte() & 0xFF;
}
return -1;
}
@Override
public int read(byte[] sink, int offset, int byteCount) {
return Buffer.this.read(sink, offset, byteCount);
}
@Override
public int available() {
return (int)Math.min(Buffer.this.size, Integer.MAX_VALUE);
}
@Override
public void close() {
}
public String toString() {
return Buffer.this + ".inputStream()";
}
};
}
public Buffer copyTo(OutputStream out) throws IOException {
return this.copyTo(out, 0L, this.size);
}
public Buffer copyTo(OutputStream out, long offset, long byteCount) throws IOException {
if (out == null) {
throw new IllegalArgumentException("out == null");
}
Util.checkOffsetAndCount(this.size, offset, byteCount);
if (byteCount == 0L) {
return this;
}
Segment s = this.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 toCopy = (int)Math.min((long)(s.limit - pos), byteCount);
out.write(s.data, pos, toCopy);
byteCount -= (long)toCopy;
offset = 0L;
s = s.next;
}
return this;
}
public Buffer copyTo(Buffer out, long offset, long byteCount) {
if (out == null) {
throw new IllegalArgumentException("out == null");
}
Util.checkOffsetAndCount(this.size, offset, byteCount);
if (byteCount == 0L) {
return this;
}
out.size += byteCount;
Segment s = this.head;
while (offset >= (long)(s.limit - s.pos)) {
offset -= (long)(s.limit - s.pos);
s = s.next;
}
while (byteCount > 0L) {
Segment copy = new Segment(s);
copy.pos = (int)((long)copy.pos + offset);
copy.limit = Math.min(copy.pos + (int)byteCount, copy.limit);
if (out.head == null) {
copy.next = copy.prev = copy;
out.head = copy.prev;
} else {
out.head.prev.push(copy);
}
byteCount -= (long)(copy.limit - copy.pos);
offset = 0L;
s = s.next;
}
return this;
}
public Buffer writeTo(OutputStream out) throws IOException {
return this.writeTo(out, this.size);
}
public Buffer writeTo(OutputStream out, long byteCount) throws IOException {
if (out == null) {
throw new IllegalArgumentException("out == null");
}
Util.checkOffsetAndCount(this.size, 0L, byteCount);
Segment s = this.head;
while (byteCount > 0L) {
int toCopy = (int)Math.min(byteCount, (long)(s.limit - s.pos));
out.write(s.data, s.pos, toCopy);
s.pos += toCopy;
this.size -= (long)toCopy;
byteCount -= (long)toCopy;
if (s.pos != s.limit) continue;
Segment toRecycle = s;
this.head = s = toRecycle.pop();
SegmentPool.recycle(toRecycle);
}
return this;
}
public Buffer readFrom(InputStream in) throws IOException {
this.readFrom(in, Long.MAX_VALUE, true);
return this;
}
public Buffer readFrom(InputStream in, long byteCount) throws IOException {
if (byteCount < 0L) {
throw new IllegalArgumentException("byteCount < 0: " + byteCount);
}
this.readFrom(in, byteCount, false);
return this;
}
private void readFrom(InputStream in, long byteCount, boolean forever) throws IOException {
if (in == null) {
throw new IllegalArgumentException("in == null");
}
while (byteCount > 0L || forever) {
Segment tail = this.writableSegment(1);
int maxToCopy = (int)Math.min(byteCount, (long)(2048 - tail.limit));
int bytesRead = in.read(tail.data, tail.limit, maxToCopy);
if (bytesRead == -1) {
if (forever) {
return;
}
throw new EOFException();
}
tail.limit += bytesRead;
this.size += (long)bytesRead;
byteCount -= (long)bytesRead;
}
}
public long completeSegmentByteCount() {
long result = this.size;
if (result == 0L) {
return 0L;
}
Segment tail = this.head.prev;
if (tail.limit < 2048 && tail.owner) {
result -= (long)(tail.limit - tail.pos);
}
return result;
}
@Override
public byte readByte() {
if (this.size == 0L) {
throw new IllegalStateException("size == 0");
}
Segment segment = this.head;
int pos = segment.pos;
int limit = segment.limit;
byte[] data = segment.data;
byte b = data[pos++];
--this.size;
if (pos == limit) {
this.head = segment.pop();
SegmentPool.recycle(segment);
} else {
segment.pos = pos;
}
return b;
}
public byte getByte(long pos) {
Util.checkOffsetAndCount(this.size, pos, 1L);
Segment s = this.head;
int segmentByteCount;
while (pos >= (long)(segmentByteCount = s.limit - s.pos)) {
pos -= (long)segmentByteCount;
s = s.next;
}
return s.data[s.pos + (int)pos];
}
@Override
public short readShort() {
if (this.size < 2L) {
throw new IllegalStateException("size < 2: " + this.size);
}
Segment segment = this.head;
int limit = segment.limit;
int pos = segment.pos;
if (limit - pos < 2) {
int s = (this.readByte() & 0xFF) << 8 | this.readByte() & 0xFF;
return (short)s;
}
byte[] data = segment.data;
int s = (data[pos++] & 0xFF) << 8 | data[pos++] & 0xFF;
this.size -= 2L;
if (pos == limit) {
this.head = segment.pop();
SegmentPool.recycle(segment);
} else {
segment.pos = pos;
}
return (short)s;
}
@Override
public int readInt() {
if (this.size < 4L) {
throw new IllegalStateException("size < 4: " + this.size);
}
Segment segment = this.head;
int limit = segment.limit;
int pos = segment.pos;
if (limit - pos < 4) {
return (this.readByte() & 0xFF) << 24 | (this.readByte() & 0xFF) << 16 | (this.readByte() & 0xFF) << 8 | this.readByte() & 0xFF;
}
byte[] data = segment.data;
int i = (data[pos++] & 0xFF) << 24 | (data[pos++] & 0xFF) << 16 | (data[pos++] & 0xFF) << 8 | data[pos++] & 0xFF;
this.size -= 4L;
if (pos == limit) {
this.head = segment.pop();
SegmentPool.recycle(segment);
} else {
segment.pos = pos;
}
return i;
}
@Override
public long readLong() {
if (this.size < 8L) {
throw new IllegalStateException("size < 8: " + this.size);
}
Segment segment = this.head;
int limit = segment.limit;
int pos = segment.pos;
if (limit - pos < 8) {
return ((long)this.readInt() & 0xFFFFFFFFL) << 32 | (long)this.readInt() & 0xFFFFFFFFL;
}
byte[] data = segment.data;
long v = ((long)data[pos++] & 0xFFL) << 56 | ((long)data[pos++] & 0xFFL) << 48 | ((long)data[pos++] & 0xFFL) << 40 | ((long)data[pos++] & 0xFFL) << 32 | ((long)data[pos++] & 0xFFL) << 24 | ((long)data[pos++] & 0xFFL) << 16 | ((long)data[pos++] & 0xFFL) << 8 | (long)data[pos++] & 0xFFL;
this.size -= 8L;
if (pos == limit) {
this.head = segment.pop();
SegmentPool.recycle(segment);
} else {
segment.pos = pos;
}
return v;
}
@Override
public short readShortLe() {
return Util.reverseBytesShort(this.readShort());
}
@Override
public int readIntLe() {
return Util.reverseBytesInt(this.readInt());
}
@Override
public long readLongLe() {
return Util.reverseBytesLong(this.readLong());
}
@Override
public long readDecimalLong() {
if (this.size == 0L) {
throw new IllegalStateException("size == 0");
}
long value = 0L;
int seen = 0;
boolean negative = false;
boolean done = false;
long overflowZone = -922337203685477580L;
long overflowDigit = -7L;
do {
Segment segment = this.head;
byte[] data = segment.data;
int pos = segment.pos;
int limit = segment.limit;
while (pos < limit) {
byte b = data[pos];
if (b >= 48 && b <= 57) {
int digit = 48 - b;
if (value < overflowZone || value == overflowZone && (long)digit < overflowDigit) {
Buffer buffer = new Buffer().writeDecimalLong(value).writeByte(b);
if (!negative) {
buffer.readByte();
}
throw new NumberFormatException("Number too large: " + buffer.readUtf8());
}
value *= 10L;
value += (long)digit;
} else if (b == 45 && seen == 0) {
negative = true;
--overflowDigit;
} else {
if (seen == 0) {
throw new NumberFormatException("Expected leading [0-9] or '-' character but was 0x" + Integer.toHexString(b));
}
done = true;
break;
}
++pos;
++seen;
}
if (pos == limit) {
this.head = segment.pop();
SegmentPool.recycle(segment);
continue;
}
segment.pos = pos;
} while (!done && this.head != null);
this.size -= (long)seen;
return negative ? value : -value;
}
@Override
public long readHexadecimalUnsignedLong() {
if (this.size == 0L) {
throw new IllegalStateException("size == 0");
}
long value = 0L;
int seen = 0;
boolean done = false;
do {
Segment segment = this.head;
byte[] data = segment.data;
int pos = segment.pos;
int limit = segment.limit;
while (pos < limit) {
int digit;
byte b = data[pos];
if (b >= 48 && b <= 57) {
digit = b - 48;
} else if (b >= 97 && b <= 102) {
digit = b - 97 + 10;
} else if (b >= 65 && b <= 70) {
digit = b - 65 + 10;
} else {
if (seen == 0) {
throw new NumberFormatException("Expected leading [0-9a-fA-F] character but was 0x" + Integer.toHexString(b));
}
done = true;
break;
}
if ((value & 0xF000000000000000L) != 0L) {
Buffer buffer = new Buffer().writeHexadecimalUnsignedLong(value).writeByte(b);
throw new NumberFormatException("Number too large: " + buffer.readUtf8());
}
value <<= 4;
value |= (long)digit;
++pos;
++seen;
}
if (pos == limit) {
this.head = segment.pop();
SegmentPool.recycle(segment);
continue;
}
segment.pos = pos;
} while (!done && this.head != null);
this.size -= (long)seen;
return value;
}
@Override
public ByteString readByteString() {
return new ByteString(this.readByteArray());
}
@Override
public ByteString readByteString(long byteCount) throws EOFException {
return new ByteString(this.readByteArray(byteCount));
}
@Override
public void readFully(Buffer sink, long byteCount) throws EOFException {
if (this.size < byteCount) {
sink.write(this, this.size);
throw new EOFException();
}
sink.write(this, byteCount);
}
@Override
public long readAll(Sink sink) throws IOException {
long byteCount = this.size;
if (byteCount > 0L) {
sink.write(this, byteCount);
}
return byteCount;
}
@Override
public String readUtf8() {
try {
return this.readString(this.size, Util.UTF_8);
}
catch (EOFException e) {
throw new AssertionError((Object)e);
}
}
@Override
public String readUtf8(long byteCount) throws EOFException {
return this.readString(byteCount, Util.UTF_8);
}
@Override
public String readString(Charset charset) {
try {
return this.readString(this.size, charset);
}
catch (EOFException e) {
throw new AssertionError((Object)e);
}
}
@Override
public String readString(long byteCount, Charset charset) throws EOFException {
Util.checkOffsetAndCount(this.size, 0L, byteCount);
if (charset == null) {
throw new IllegalArgumentException("charset == null");
}
if (byteCount > Integer.MAX_VALUE) {
throw new IllegalArgumentException("byteCount > Integer.MAX_VALUE: " + byteCount);
}
if (byteCount == 0L) {
return "";
}
Segment s = this.head;
if ((long)s.pos + byteCount > (long)s.limit) {
return new String(this.readByteArray(byteCount), charset);
}
String result = new String(s.data, s.pos, (int)byteCount, charset);
s.pos = (int)((long)s.pos + byteCount);
this.size -= byteCount;
if (s.pos == s.limit) {
this.head = s.pop();
SegmentPool.recycle(s);
}
return result;
}
@Override
public String readUtf8Line() throws EOFException {
long newline = this.indexOf((byte)10);
if (newline == -1L) {
return this.size != 0L ? this.readUtf8(this.size) : null;
}
return this.readUtf8Line(newline);
}
@Override
public String readUtf8LineStrict() throws EOFException {
long newline = this.indexOf((byte)10);
if (newline == -1L) {
Buffer data = new Buffer();
this.copyTo(data, 0L, Math.min(32L, this.size));
throw new EOFException("\\n not found: size=" + this.size() + " content=" + data.readByteString().hex() + "...");
}
return this.readUtf8Line(newline);
}
String readUtf8Line(long newline) throws EOFException {
if (newline > 0L && this.getByte(newline - 1L) == 13) {
String result = this.readUtf8(newline - 1L);
this.skip(2L);
return result;
}
String result = this.readUtf8(newline);
this.skip(1L);
return result;
}
@Override
public int readUtf8CodePoint() throws EOFException {
int min;
int byteCount;
int codePoint;
if (this.size == 0L) {
throw new EOFException();
}
byte b0 = this.getByte(0L);
if ((b0 & 0x80) == 0) {
codePoint = b0 & 0x7F;
byteCount = 1;
min = 0;
} else if ((b0 & 0xE0) == 192) {
codePoint = b0 & 0x1F;
byteCount = 2;
min = 128;
} else if ((b0 & 0xF0) == 224) {
codePoint = b0 & 0xF;
byteCount = 3;
min = 2048;
} else if ((b0 & 0xF8) == 240) {
codePoint = b0 & 7;
byteCount = 4;
min = 65536;
} else {
this.skip(1L);
return 65533;
}
if (this.size < (long)byteCount) {
throw new EOFException("size < " + byteCount + ": " + this.size + " (to read code point prefixed 0x" + Integer.toHexString(b0) + ")");
}
for (int i = 1; i < byteCount; ++i) {
byte b = this.getByte(i);
if ((b & 0xC0) == 128) {
codePoint <<= 6;
codePoint |= b & 0x3F;
continue;
}
this.skip(i);
return 65533;
}
this.skip(byteCount);
if (codePoint > 0x10FFFF) {
return 65533;
}
if (codePoint >= 55296 && codePoint <= 57343) {
return 65533;
}
if (codePoint < min) {
return 65533;
}
return codePoint;
}
@Override
public byte[] readByteArray() {
try {
return this.readByteArray(this.size);
}
catch (EOFException e) {
throw new AssertionError((Object)e);
}
}
@Override
public byte[] readByteArray(long byteCount) throws EOFException {
Util.checkOffsetAndCount(this.size, 0L, byteCount);
if (byteCount > Integer.MAX_VALUE) {
throw new IllegalArgumentException("byteCount > Integer.MAX_VALUE: " + byteCount);
}
byte[] result = new byte[(int)byteCount];
this.readFully(result);
return result;
}
@Override
public int read(byte[] sink) {
return this.read(sink, 0, sink.length);
}
@Override
public void readFully(byte[] sink) throws EOFException {
int read;
for (int offset = 0; offset < sink.length; offset += read) {
read = this.read(sink, offset, sink.length - offset);
if (read != -1) continue;
throw new EOFException();
}
}
@Override
public int read(byte[] sink, int offset, int byteCount) {
Util.checkOffsetAndCount(sink.length, offset, byteCount);
Segment s = this.head;
if (s == null) {
return -1;
}
int toCopy = Math.min(byteCount, s.limit - s.pos);
System.arraycopy(s.data, s.pos, sink, offset, toCopy);
s.pos += toCopy;
this.size -= (long)toCopy;
if (s.pos == s.limit) {
this.head = s.pop();
SegmentPool.recycle(s);
}
return toCopy;
}
public void clear() {
try {
this.skip(this.size);
}
catch (EOFException e) {
throw new AssertionError((Object)e);
}
}
@Override
public void skip(long byteCount) throws EOFException {
while (byteCount > 0L) {
if (this.head == null) {
throw new EOFException();
}
int toSkip = (int)Math.min(byteCount, (long)(this.head.limit - this.head.pos));
this.size -= (long)toSkip;
byteCount -= (long)toSkip;
this.head.pos += toSkip;
if (this.head.pos != this.head.limit) continue;
Segment toRecycle = this.head;
this.head = toRecycle.pop();
SegmentPool.recycle(toRecycle);
}
}
@Override
public Buffer write(ByteString byteString) {
if (byteString == null) {
throw new IllegalArgumentException("byteString == null");
}
byteString.write(this);
return this;
}
@Override
public Buffer writeUtf8(String string) {
return this.writeUtf8(string, 0, string.length());
}
@Override
public Buffer writeUtf8(String string, int beginIndex, int endIndex) {
if (string == null) {
throw new IllegalArgumentException("string == null");
}
if (beginIndex < 0) {
throw new IllegalAccessError("beginIndex < 0: " + beginIndex);
}
if (endIndex < beginIndex) {
throw new IllegalArgumentException("endIndex < beginIndex: " + endIndex + " < " + beginIndex);
}
if (endIndex > string.length()) {
throw new IllegalArgumentException("endIndex > string.length: " + endIndex + " > " + string.length());
}
int i = beginIndex;
while (i < endIndex) {
char low;
char c = string.charAt(i);
if (c < '\u0080') {
Segment tail = this.writableSegment(1);
byte[] data = tail.data;
int segmentOffset = tail.limit - i;
int runLimit = Math.min(endIndex, 2048 - segmentOffset);
data[segmentOffset + i++] = (byte)c;
while (i < runLimit && (c = string.charAt(i)) < '\u0080') {
data[segmentOffset + i++] = (byte)c;
}
int runSize = i + segmentOffset - tail.limit;
tail.limit += runSize;
this.size += (long)runSize;
continue;
}
if (c < '\u0800') {
this.writeByte(c >> 6 | 0xC0);
this.writeByte(c & 0x3F | 0x80);
++i;
continue;
}
if (c < '\ud800' || c > '\udfff') {
this.writeByte(c >> 12 | 0xE0);
this.writeByte(c >> 6 & 0x3F | 0x80);
this.writeByte(c & 0x3F | 0x80);
++i;
continue;
}
char c2 = low = i + 1 < endIndex ? string.charAt(i + 1) : (char)'\u0000';
if (c > '\udbff' || low < '\udc00' || low > '\udfff') {
this.writeByte(63);
++i;
continue;
}
int codePoint = 65536 + ((c & 0xFFFF27FF) << 10 | low & 0xFFFF23FF);
this.writeByte(codePoint >> 18 | 0xF0);
this.writeByte(codePoint >> 12 & 0x3F | 0x80);
this.writeByte(codePoint >> 6 & 0x3F | 0x80);
this.writeByte(codePoint & 0x3F | 0x80);
i += 2;
}
return this;
}
@Override
public Buffer writeUtf8CodePoint(int codePoint) {
if (codePoint < 128) {
this.writeByte(codePoint);
} else if (codePoint < 2048) {
this.writeByte(codePoint >> 6 | 0xC0);
this.writeByte(codePoint & 0x3F | 0x80);
} else if (codePoint < 65536) {
if (codePoint >= 55296 && codePoint <= 57343) {
throw new IllegalArgumentException("Unexpected code point: " + Integer.toHexString(codePoint));
}
this.writeByte(codePoint >> 12 | 0xE0);
this.writeByte(codePoint >> 6 & 0x3F | 0x80);
this.writeByte(codePoint & 0x3F | 0x80);
} else if (codePoint <= 0x10FFFF) {
this.writeByte(codePoint >> 18 | 0xF0);
this.writeByte(codePoint >> 12 & 0x3F | 0x80);
this.writeByte(codePoint >> 6 & 0x3F | 0x80);
this.writeByte(codePoint & 0x3F | 0x80);
} else {
throw new IllegalArgumentException("Unexpected code point: " + Integer.toHexString(codePoint));
}
return this;
}
@Override
public Buffer writeString(String string, Charset charset) {
return this.writeString(string, 0, string.length(), charset);
}
@Override
public Buffer writeString(String string, int beginIndex, int endIndex, Charset charset) {
if (string == null) {
throw new IllegalArgumentException("string == null");
}
if (beginIndex < 0) {
throw new IllegalAccessError("beginIndex < 0: " + beginIndex);
}
if (endIndex < beginIndex) {
throw new IllegalArgumentException("endIndex < beginIndex: " + endIndex + " < " + beginIndex);
}
if (endIndex > string.length()) {
throw new IllegalArgumentException("endIndex > string.length: " + endIndex + " > " + string.length());
}
if (charset == null) {
throw new IllegalArgumentException("charset == null");
}
if (charset.equals(Util.UTF_8)) {
return this.writeUtf8(string);
}
byte[] data = string.substring(beginIndex, endIndex).getBytes(charset);
return this.write(data, 0, data.length);
}
@Override
public Buffer write(byte[] source) {
if (source == null) {
throw new IllegalArgumentException("source == null");
}
return this.write(source, 0, source.length);
}
@Override
public Buffer write(byte[] source, int offset, int byteCount) {
if (source == null) {
throw new IllegalArgumentException("source == null");
}
Util.checkOffsetAndCount(source.length, offset, byteCount);
int limit = offset + byteCount;
while (offset < limit) {
Segment tail = this.writableSegment(1);
int toCopy = Math.min(limit - offset, 2048 - tail.limit);
System.arraycopy(source, offset, tail.data, tail.limit, toCopy);
offset += toCopy;
tail.limit += toCopy;
}
this.size += (long)byteCount;
return this;
}
@Override
public long writeAll(Source source) throws IOException {
long readCount;
if (source == null) {
throw new IllegalArgumentException("source == null");
}
long totalBytesRead = 0L;
while ((readCount = source.read(this, 2048L)) != -1L) {
totalBytesRead += readCount;
}
return totalBytesRead;
}
@Override
public BufferedSink write(Source source, long byteCount) throws IOException {
while (byteCount > 0L) {
long read = source.read(this, byteCount);
if (read == -1L) {
throw new EOFException();
}
byteCount -= read;
}
return this;
}
@Override
public Buffer writeByte(int b) {
Segment tail = this.writableSegment(1);
tail.data[tail.limit++] = (byte)b;
++this.size;
return this;
}
@Override
public Buffer writeShort(int s) {
Segment tail = this.writableSegment(2);
byte[] data = tail.data;
int limit = tail.limit;
data[limit++] = (byte)(s >>> 8 & 0xFF);
data[limit++] = (byte)(s & 0xFF);
tail.limit = limit;
this.size += 2L;
return this;
}
@Override
public Buffer writeShortLe(int s) {
return this.writeShort(Util.reverseBytesShort((short)s));
}
@Override
public Buffer writeInt(int i) {
Segment tail = this.writableSegment(4);
byte[] data = tail.data;
int limit = tail.limit;
data[limit++] = (byte)(i >>> 24 & 0xFF);
data[limit++] = (byte)(i >>> 16 & 0xFF);
data[limit++] = (byte)(i >>> 8 & 0xFF);
data[limit++] = (byte)(i & 0xFF);
tail.limit = limit;
this.size += 4L;
return this;
}
@Override
public Buffer writeIntLe(int i) {
return this.writeInt(Util.reverseBytesInt(i));
}
@Override
public Buffer writeLong(long v) {
Segment tail = this.writableSegment(8);
byte[] data = tail.data;
int limit = tail.limit;
data[limit++] = (byte)(v >>> 56 & 0xFFL);
data[limit++] = (byte)(v >>> 48 & 0xFFL);
data[limit++] = (byte)(v >>> 40 & 0xFFL);
data[limit++] = (byte)(v >>> 32 & 0xFFL);
data[limit++] = (byte)(v >>> 24 & 0xFFL);
data[limit++] = (byte)(v >>> 16 & 0xFFL);
data[limit++] = (byte)(v >>> 8 & 0xFFL);
data[limit++] = (byte)(v & 0xFFL);
tail.limit = limit;
this.size += 8L;
return this;
}
@Override
public Buffer writeLongLe(long v) {
return this.writeLong(Util.reverseBytesLong(v));
}
@Override
public Buffer writeDecimalLong(long v) {
int width;
if (v == 0L) {
return this.writeByte(48);
}
boolean negative = false;
if (v < 0L) {
if ((v = -v) < 0L) {
return this.writeUtf8("-9223372036854775808");
}
negative = true;
}
int n = v < 100000000L ? (v < 10000L ? (v < 100L ? (v < 10L ? 1 : 2) : (v < 1000L ? 3 : 4)) : (v < 1000000L ? (v < 100000L ? 5 : 6) : (v < 10000000L ? 7 : 8))) : (v < 1000000000000L ? (v < 10000000000L ? (v < 1000000000L ? 9 : 10) : (v < 100000000000L ? 11 : 12)) : (v < 1000000000000000L ? (v < 10000000000000L ? 13 : (v < 100000000000000L ? 14 : 15)) : (v < 100000000000000000L ? (v < 10000000000000000L ? 16 : 17) : (width = v < 1000000000000000000L ? 18 : 19))));
if (negative) {
++width;
}
Segment tail = this.writableSegment(width);
byte[] data = tail.data;
int pos = tail.limit + width;
while (v != 0L) {
int digit = (int)(v % 10L);
data[--pos] = DIGITS[digit];
v /= 10L;
}
if (negative) {
data[--pos] = 45;
}
tail.limit += width;
this.size += (long)width;
return this;
}
@Override
public Buffer writeHexadecimalUnsignedLong(long v) {
if (v == 0L) {
return this.writeByte(48);
}
int width = Long.numberOfTrailingZeros(Long.highestOneBit(v)) / 4 + 1;
Segment tail = this.writableSegment(width);
byte[] data = tail.data;
int start = tail.limit;
for (int pos = tail.limit + width - 1; pos >= start; --pos) {
data[pos] = DIGITS[(int)(v & 0xFL)];
v >>>= 4;
}
tail.limit += width;
this.size += (long)width;
return this;
}
Segment writableSegment(int minimumCapacity) {
if (minimumCapacity < 1 || minimumCapacity > 2048) {
throw new IllegalArgumentException();
}
if (this.head == null) {
this.head.next = this.head.prev = (this.head = SegmentPool.take());
return this.head.prev;
}
Segment tail = this.head.prev;
if (tail.limit + minimumCapacity > 2048 || !tail.owner) {
tail = tail.push(SegmentPool.take());
}
return tail;
}
@Override
public void write(Buffer source, long byteCount) {
if (source == null) {
throw new IllegalArgumentException("source == null");
}
if (source == this) {
throw new IllegalArgumentException("source == this");
}
Util.checkOffsetAndCount(source.size, 0L, byteCount);
while (byteCount > 0L) {
if (byteCount < (long)(source.head.limit - source.head.pos)) {
Segment tail;
Segment segment = tail = this.head != null ? this.head.prev : null;
if (tail != null && tail.owner && byteCount + (long)tail.limit - (long)(tail.shared ? 0 : tail.pos) <= 2048L) {
source.head.writeTo(tail, (int)byteCount);
source.size -= byteCount;
this.size += byteCount;
return;
}
source.head = source.head.split((int)byteCount);
}
Segment segmentToMove = source.head;
long movedByteCount = segmentToMove.limit - segmentToMove.pos;
source.head = segmentToMove.pop();
if (this.head == null) {
this.head.next = this.head.prev = (this.head = segmentToMove);
} else {
Segment tail = this.head.prev;
tail = tail.push(segmentToMove);
tail.compact();
}
source.size -= movedByteCount;
this.size += movedByteCount;
byteCount -= movedByteCount;
}
}
@Override
public long read(Buffer sink, long byteCount) {
if (sink == null) {
throw new IllegalArgumentException("sink == null");
}
if (byteCount < 0L) {
throw new IllegalArgumentException("byteCount < 0: " + byteCount);
}
if (this.size == 0L) {
return -1L;
}
if (byteCount > this.size) {
byteCount = this.size;
}
sink.write(this, byteCount);
return byteCount;
}
@Override
public long indexOf(byte b) {
return this.indexOf(b, 0L);
}
@Override
public long indexOf(byte b, long fromIndex) {
if (fromIndex < 0L) {
throw new IllegalArgumentException("fromIndex < 0");
}
Segment s = this.head;
if (s == null) {
return -1L;
}
long offset = 0L;
do {
int segmentByteCount;
if (fromIndex >= (long)(segmentByteCount = s.limit - s.pos)) {
fromIndex -= (long)segmentByteCount;
} else {
byte[] data = s.data;
int limit = s.limit;
for (int pos = (int)((long)s.pos + fromIndex); pos < limit; ++pos) {
if (data[pos] != b) continue;
return offset + (long)pos - (long)s.pos;
}
fromIndex = 0L;
}
offset += (long)segmentByteCount;
} while ((s = s.next) != this.head);
return -1L;
}
@Override
public long indexOf(ByteString bytes) throws IOException {
return this.indexOf(bytes, 0L);
}
@Override
public long indexOf(ByteString bytes, long fromIndex) throws IOException {
if (bytes.size() == 0) {
throw new IllegalArgumentException("bytes is empty");
}
while ((fromIndex = this.indexOf(bytes.getByte(0), fromIndex)) != -1L) {
if (this.rangeEquals(fromIndex, bytes)) {
return fromIndex;
}
++fromIndex;
}
return -1L;
}
@Override
public long indexOfElement(ByteString targetBytes) {
return this.indexOfElement(targetBytes, 0L);
}
@Override
public long indexOfElement(ByteString targetBytes, long fromIndex) {
if (fromIndex < 0L) {
throw new IllegalArgumentException("fromIndex < 0");
}
Segment s = this.head;
if (s == null) {
return -1L;
}
long offset = 0L;
byte[] toFind = targetBytes.toByteArray();
do {
int segmentByteCount;
if (fromIndex >= (long)(segmentByteCount = s.limit - s.pos)) {
fromIndex -= (long)segmentByteCount;
} else {
byte[] data = s.data;
long limit = s.limit;
for (long pos = (long)s.pos + fromIndex; pos < limit; ++pos) {
byte b = data[(int)pos];
for (byte targetByte : toFind) {
if (b != targetByte) continue;
return offset + pos - (long)s.pos;
}
}
fromIndex = 0L;
}
offset += (long)segmentByteCount;
} while ((s = s.next) != this.head);
return -1L;
}
boolean rangeEquals(long offset, ByteString bytes) {
int byteCount = bytes.size();
if (this.size - offset < (long)byteCount) {
return false;
}
for (int i = 0; i < byteCount; ++i) {
if (this.getByte(offset + (long)i) == bytes.getByte(i)) continue;
return false;
}
return true;
}
@Override
public void flush() {
}
@Override
public void close() {
}
@Override
public Timeout timeout() {
return Timeout.NONE;
}
List<Integer> segmentSizes() {
if (this.head == null) {
return Collections.emptyList();
}
ArrayList<Integer> result = new ArrayList<Integer>();
result.add(this.head.limit - this.head.pos);
Segment s = this.head.next;
while (s != this.head) {
result.add(s.limit - s.pos);
s = s.next;
}
return result;
}
public boolean equals(Object o) {
long count;
if (this == o) {
return true;
}
if (!(o instanceof Buffer)) {
return false;
}
Buffer that = (Buffer)o;
if (this.size != that.size) {
return false;
}
if (this.size == 0L) {
return true;
}
Segment sa = this.head;
Segment sb = that.head;
int posA = sa.pos;
int posB = sb.pos;
for (long pos = 0L; pos < this.size; pos += count) {
count = Math.min(sa.limit - posA, sb.limit - posB);
int i = 0;
while ((long)i < count) {
if (sa.data[posA++] != sb.data[posB++]) {
return false;
}
++i;
}
if (posA == sa.limit) {
sa = sa.next;
posA = sa.pos;
}
if (posB != sb.limit) continue;
sb = sb.next;
posB = sb.pos;
}
return true;
}
public int hashCode() {
Segment s = this.head;
if (s == null) {
return 0;
}
int result = 1;
do {
int limit = s.limit;
for (int pos = s.pos; pos < limit; ++pos) {
result = 31 * result + s.data[pos];
}
} while ((s = s.next) != this.head);
return result;
}
public String toString() {
if (this.size == 0L) {
return "Buffer[size=0]";
}
if (this.size <= 16L) {
ByteString data = this.clone().readByteString();
return String.format("Buffer[size=%s data=%s]", this.size, data.hex());
}
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update(this.head.data, this.head.pos, this.head.limit - this.head.pos);
Segment s = this.head.next;
while (s != this.head) {
md5.update(s.data, s.pos, s.limit - s.pos);
s = s.next;
}
return String.format("Buffer[size=%s md5=%s]", this.size, ByteString.of(md5.digest()).hex());
}
catch (NoSuchAlgorithmException e) {
throw new AssertionError();
}
}
public Buffer clone() {
Buffer result = new Buffer();
if (this.size == 0L) {
return result;
}
result.head.next = result.head.prev = (result.head = new Segment(this.head));
Segment s = this.head.next;
while (s != this.head) {
result.head.prev.push(new Segment(s));
s = s.next;
}
result.size = this.size;
return result;
}
public ByteString snapshot() {
if (this.size > Integer.MAX_VALUE) {
throw new IllegalArgumentException("size > Integer.MAX_VALUE: " + this.size);
}
return this.snapshot((int)this.size);
}
public ByteString snapshot(int byteCount) {
if (byteCount == 0) {
return ByteString.EMPTY;
}
return new SegmentedByteString(this, byteCount);
}
}