Update #0 - First Release

This commit is contained in:
LAX1DUDE
2022-12-25 01:12:28 -08:00
commit e7179fad45
2154 changed files with 256324 additions and 0 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,252 @@
package net.lax1dude.eaglercraft.v1_8.netty;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class ByteBufEaglercraftImpl extends AbstractByteBuf {
private ByteBuffer internal;
public ByteBufEaglercraftImpl(ByteBuffer internal, int maxCapacity) {
super(maxCapacity);
if(internal.order() != ByteOrder.BIG_ENDIAN) {
this.internal = internal.order(ByteOrder.BIG_ENDIAN);
}else {
this.internal = internal;
}
}
@Override
protected byte _getByte(int index) {
return internal.get(index);
}
@Override
protected short _getShort(int index) {
return internal.getShort(index);
}
@Override
protected int _getUnsignedMedium(int index) {
return ((internal.get(index) & 0xFF) << 16) | ((internal.get(index + 1) & 0xFF) << 8) |
(internal.get(index + 2) & 0xFF);
}
@Override
protected int _getInt(int index) {
return internal.getInt(index);
}
@Override
protected long _getLong(int index) {
return internal.getLong(index);
}
@Override
protected void _setByte(int index, int value) {
internal.put(index, (byte)value);
}
@Override
protected void _setShort(int index, int value) {
internal.putShort(index, (short)value);
}
@Override
protected void _setMedium(int index, int value) {
internal.put(index, (byte)((value >> 16) & 0xFF));
internal.put(index + 1, (byte)((value >> 8) & 0xFF));
internal.put(index + 2, (byte)(value & 0xFF));
}
@Override
protected void _setInt(int index, int value) {
internal.putInt(index, value);
}
@Override
protected void _setLong(int index, long value) {
internal.putLong(index, value);
}
@Override
public int capacity() {
return internal.capacity();
}
@Override
public ByteBuf capacity(int newCapacity) {
if(newCapacity > internal.capacity()) {
ByteBuffer newCap = ByteBuffer.wrap(new byte[(int)(newCapacity * 1.5f)]);
NioBufferFunctions.put(newCap, 0, internal, 0, internal.capacity());
newCap.clear();
internal = newCap;
}
return this;
}
@Override
public ByteOrder order() {
return ByteOrder.BIG_ENDIAN;
}
@Override
public ByteBuf order(ByteOrder endianness) {
throw new UnsupportedOperationException("Not supported as it is not used by Eaglercraft");
}
@Override
public ByteBuf unwrap() {
return this;
}
@Override
public boolean isDirect() {
return false;
}
@Override
public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
if(!(dst instanceof ByteBufEaglercraftImpl)) {
throw new IllegalArgumentException("The buffer passed is not an Eaglercraft byte buffer!");
}
NioBufferFunctions.put(((ByteBufEaglercraftImpl)dst).internal, dstIndex, internal, index, length);
return this;
}
@Override
public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
NioBufferFunctions.get(internal, index, dst, dstIndex, length);
return this;
}
@Override
public ByteBuf getBytes(int index, ByteBuffer dst) {
NioBufferFunctions.put(dst, dst.position(), internal, index, dst.remaining());
dst.position(dst.limit());
return this;
}
@Override
public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
byte[] buf = new byte[length];
NioBufferFunctions.get(internal, index, buf);
out.write(buf);
return this;
}
@Override
public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
if(!(src instanceof ByteBufEaglercraftImpl)) {
throw new IllegalArgumentException("The buffer passed is not an Eaglercraft byte buffer!");
}
NioBufferFunctions.put(internal, index, ((ByteBufEaglercraftImpl)src).internal, srcIndex, length);
return this;
}
@Override
public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
NioBufferFunctions.put(internal, index, src, srcIndex, length);
return this;
}
@Override
public ByteBuf setBytes(int index, ByteBuffer src) {
NioBufferFunctions.put(internal, index, src, src.position(), src.remaining());
src.position(src.limit());
return this;
}
@Override
public int setBytes(int index, InputStream in, int length) throws IOException {
byte[] buf = new byte[length];
int r = in.read(buf, 0, length);
if(r > 0) {
NioBufferFunctions.put(internal, index, buf, 0, r);
}
return r;
}
@Override
public ByteBuf copy(int index, int length) {
byte[] cpy = new byte[length];
NioBufferFunctions.get(internal, index, cpy);
return new ByteBufEaglercraftImpl(ByteBuffer.wrap(cpy), maxCapacity());
}
@Override
public int nioBufferCount() {
return 1;
}
@Override
public ByteBuffer nioBuffer(int index, int length) {
//return internal.slice(index, length);
throw new UnsupportedOperationException("Not supported in JDK 8");
}
@Override
public ByteBuffer internalNioBuffer(int index, int length) {
internal.position(index).limit(index + length);
return internal;
}
@Override
public ByteBuffer[] nioBuffers(int index, int length) {
//return new ByteBuffer[] { internal.slice(index, length) };
throw new UnsupportedOperationException("Not supported in JDK 8");
}
@Override
public boolean hasArray() {
return true;
}
@Override
public byte[] array() {
return internal.array();
}
@Override
public int arrayOffset() {
return 0;
}
@Override
public boolean hasMemoryAddress() {
return false;
}
@Override
public long memoryAddress() {
return 0;
}
@Override
public ByteBuf slice(int index, int length) {
//return new ByteBufEaglercraftImpl(internal.slice(index, length), maxCapacity());
throw new UnsupportedOperationException("Not supported in JDK 8");
}
@Override
public ByteBuf duplicate() {
return new ByteBufEaglercraftImpl(internal.duplicate(), maxCapacity());
}
}

View File

@ -0,0 +1,303 @@
/*
* Copyright 2012 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package net.lax1dude.eaglercraft.v1_8.netty;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
/**
* An {@link InputStream} which reads data from a {@link ByteBuf}.
* <p>
* A read operation against this stream will occur at the {@code readerIndex} of
* its underlying buffer and the {@code readerIndex} will increase during the
* read operation. Please note that it only reads up to the number of readable
* bytes determined at the moment of construction. Therefore, updating
* {@link ByteBuf#writerIndex()} will not affect the return value of
* {@link #available()}.
* <p>
* This stream implements {@link DataInput} for your convenience. The endianness
* of the stream is not always big endian but depends on the endianness of the
* underlying buffer.
*
* @see ByteBufOutputStream
*/
public class ByteBufInputStream extends InputStream implements DataInput {
private final ByteBuf buffer;
private final int startIndex;
private final int endIndex;
/**
* To preserve backwards compatibility (which didn't transfer ownership) we
* support a conditional flag which indicates if {@link #buffer} should be
* released when this {@link InputStream} is closed. However in future releases
* ownership should always be transferred and callers of this class should call
* {@link ReferenceCounted#retain()} if necessary.
*/
private boolean releaseOnClose;
/**
* Creates a new stream which reads data from the specified {@code buffer}
* starting at the current {@code readerIndex} and ending at the current
* {@code writerIndex}.
*
* @param buffer The buffer which provides the content for this
* {@link InputStream}.
*/
public ByteBufInputStream(ByteBuf buffer) {
this(buffer, buffer.readableBytes());
}
/**
* Creates a new stream which reads data from the specified {@code buffer}
* starting at the current {@code readerIndex} and ending at
* {@code readerIndex + length}.
*
* @param buffer The buffer which provides the content for this
* {@link InputStream}.
* @param length The length of the buffer to use for this {@link InputStream}.
* @throws IndexOutOfBoundsException if {@code readerIndex + length} is greater
* than {@code writerIndex}
*/
public ByteBufInputStream(ByteBuf buffer, int length) {
this(buffer, length, false);
}
/**
* Creates a new stream which reads data from the specified {@code buffer}
* starting at the current {@code readerIndex} and ending at the current
* {@code writerIndex}.
*
* @param buffer The buffer which provides the content for this
* {@link InputStream}.
* @param releaseOnClose {@code true} means that when {@link #close()} is called
* then {@link ByteBuf#release()} will be called on
* {@code buffer}.
*/
public ByteBufInputStream(ByteBuf buffer, boolean releaseOnClose) {
this(buffer, buffer.readableBytes(), releaseOnClose);
}
/**
* Creates a new stream which reads data from the specified {@code buffer}
* starting at the current {@code readerIndex} and ending at
* {@code readerIndex + length}.
*
* @param buffer The buffer which provides the content for this
* {@link InputStream}.
* @param length The length of the buffer to use for this
* {@link InputStream}.
* @param releaseOnClose {@code true} means that when {@link #close()} is called
* then {@link ByteBuf#release()} will be called on
* {@code buffer}.
* @throws IndexOutOfBoundsException if {@code readerIndex + length} is greater
* than {@code writerIndex}
*/
public ByteBufInputStream(ByteBuf buffer, int length, boolean releaseOnClose) {
if (buffer == null) {
throw new NullPointerException("buffer");
}
if (length < 0) {
throw new IllegalArgumentException("length: " + length);
}
if (length > buffer.readableBytes()) {
throw new IndexOutOfBoundsException(
"Too many bytes to be read - Needs " + length + ", maximum is " + buffer.readableBytes());
}
this.releaseOnClose = releaseOnClose;
this.buffer = buffer;
startIndex = buffer.readerIndex();
endIndex = startIndex + length;
buffer.markReaderIndex();
}
/**
* Returns the number of read bytes by this stream so far.
*/
public int readBytes() {
return buffer.readerIndex() - startIndex;
}
@Override
public int available() throws IOException {
return endIndex - buffer.readerIndex();
}
@Override
public void mark(int readlimit) {
buffer.markReaderIndex();
}
@Override
public boolean markSupported() {
return true;
}
@Override
public int read() throws IOException {
if (!buffer.isReadable()) {
return -1;
}
return buffer.readByte() & 0xff;
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
int available = available();
if (available == 0) {
return -1;
}
len = Math.min(available, len);
buffer.readBytes(b, off, len);
return len;
}
@Override
public void reset() throws IOException {
buffer.resetReaderIndex();
}
@Override
public long skip(long n) throws IOException {
if (n > Integer.MAX_VALUE) {
return skipBytes(Integer.MAX_VALUE);
} else {
return skipBytes((int) n);
}
}
@Override
public boolean readBoolean() throws IOException {
checkAvailable(1);
return read() != 0;
}
@Override
public byte readByte() throws IOException {
if (!buffer.isReadable()) {
throw new EOFException();
}
return buffer.readByte();
}
@Override
public char readChar() throws IOException {
return (char) readShort();
}
@Override
public double readDouble() throws IOException {
return Double.longBitsToDouble(readLong());
}
@Override
public float readFloat() throws IOException {
return Float.intBitsToFloat(readInt());
}
@Override
public void readFully(byte[] b) throws IOException {
readFully(b, 0, b.length);
}
@Override
public void readFully(byte[] b, int off, int len) throws IOException {
checkAvailable(len);
buffer.readBytes(b, off, len);
}
@Override
public int readInt() throws IOException {
checkAvailable(4);
return buffer.readInt();
}
private final StringBuilder lineBuf = new StringBuilder();
@Override
public String readLine() throws IOException {
lineBuf.setLength(0);
loop: while (true) {
if (!buffer.isReadable()) {
return lineBuf.length() > 0 ? lineBuf.toString() : null;
}
int c = buffer.readUnsignedByte();
switch (c) {
case '\n':
break loop;
case '\r':
if (buffer.isReadable() && (char) buffer.getUnsignedByte(buffer.readerIndex()) == '\n') {
buffer.skipBytes(1);
}
break loop;
default:
lineBuf.append((char) c);
}
}
return lineBuf.toString();
}
@Override
public long readLong() throws IOException {
checkAvailable(8);
return buffer.readLong();
}
@Override
public short readShort() throws IOException {
checkAvailable(2);
return buffer.readShort();
}
@Override
public String readUTF() throws IOException {
return DataInputStream.readUTF(this);
}
@Override
public int readUnsignedByte() throws IOException {
return readByte() & 0xff;
}
@Override
public int readUnsignedShort() throws IOException {
return readShort() & 0xffff;
}
@Override
public int skipBytes(int n) throws IOException {
int nBytes = Math.min(available(), n);
buffer.skipBytes(nBytes);
return nBytes;
}
private void checkAvailable(int fieldSize) throws IOException {
if (fieldSize < 0) {
throw new IndexOutOfBoundsException("fieldSize cannot be a negative number");
}
if (fieldSize > available()) {
throw new EOFException("fieldSize is too long! Length is " + fieldSize + ", but maximum is " + available());
}
}
}

View File

@ -0,0 +1,144 @@
/*
* Copyright 2012 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package net.lax1dude.eaglercraft.v1_8.netty;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
/**
* An {@link OutputStream} which writes data to a {@link ByteBuf}.
* <p>
* A write operation against this stream will occur at the {@code writerIndex}
* of its underlying buffer and the {@code writerIndex} will increase during the
* write operation.
* <p>
* This stream implements {@link DataOutput} for your convenience. The
* endianness of the stream is not always big endian but depends on the
* endianness of the underlying buffer.
*
* @see ByteBufInputStream
*/
public class ByteBufOutputStream extends OutputStream implements DataOutput {
private final ByteBuf buffer;
private final int startIndex;
private final DataOutputStream utf8out = new DataOutputStream(this);
/**
* Creates a new stream which writes data to the specified {@code buffer}.
*/
public ByteBufOutputStream(ByteBuf buffer) {
if (buffer == null) {
throw new NullPointerException("buffer");
}
this.buffer = buffer;
startIndex = buffer.writerIndex();
}
/**
* Returns the number of written bytes by this stream so far.
*/
public int writtenBytes() {
return buffer.writerIndex() - startIndex;
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
if (len == 0) {
return;
}
buffer.writeBytes(b, off, len);
}
@Override
public void write(byte[] b) throws IOException {
buffer.writeBytes(b);
}
@Override
public void write(int b) throws IOException {
buffer.writeByte(b);
}
@Override
public void writeBoolean(boolean v) throws IOException {
buffer.writeBoolean(v);
}
@Override
public void writeByte(int v) throws IOException {
buffer.writeByte(v);
}
@Override
public void writeBytes(String s) throws IOException {
buffer.writeBytes(s.getBytes(StandardCharsets.UTF_8));
}
@Override
public void writeChar(int v) throws IOException {
buffer.writeChar(v);
}
@Override
public void writeChars(String s) throws IOException {
int len = s.length();
for (int i = 0; i < len; i++) {
buffer.writeChar(s.charAt(i));
}
}
@Override
public void writeDouble(double v) throws IOException {
buffer.writeDouble(v);
}
@Override
public void writeFloat(float v) throws IOException {
buffer.writeFloat(v);
}
@Override
public void writeInt(int v) throws IOException {
buffer.writeInt(v);
}
@Override
public void writeLong(long v) throws IOException {
buffer.writeLong(v);
}
@Override
public void writeShort(int v) throws IOException {
buffer.writeShort((short) v);
}
@Override
public void writeUTF(String s) throws IOException {
utf8out.writeUTF(s);
}
/**
* Returns the buffer where this stream is writing data.
*/
public ByteBuf buffer() {
return buffer;
}
}

View File

@ -0,0 +1,598 @@
/*
* Copyright 2012 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package net.lax1dude.eaglercraft.v1_8.netty;
import net.lax1dude.eaglercraft.v1_8.EagUtils;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import java.nio.charset.StandardCharsets;
import static net.lax1dude.eaglercraft.v1_8.netty.ObjectUtil.checkNotNull;
/**
* A collection of utility methods that is related with handling
* {@link ByteBuf}, such as the generation of hex dump and swapping an integer's
* byte order.
*/
public final class ByteBufUtil {
private static final byte WRITE_UTF_UNKNOWN = (byte) '?';
private static final int MAX_BYTES_PER_CHAR_UTF8 = 3;
/**
* Decode a 2-digit hex byte from within a string.
*/
public static byte decodeHexByte(CharSequence s, int pos) {
return (byte)EagUtils.decodeHexByte(s, pos);
}
/**
* Calculates the hash code of the specified buffer. This method is useful when
* implementing a new buffer type.
*/
public static int hashCode(ByteBuf buffer) {
final int aLen = buffer.readableBytes();
final int intCount = aLen >>> 2;
final int byteCount = aLen & 3;
int hashCode = 1;
int arrayIndex = buffer.readerIndex();
if (buffer.order() == ByteOrder.BIG_ENDIAN) {
for (int i = intCount; i > 0; i--) {
hashCode = 31 * hashCode + buffer.getInt(arrayIndex);
arrayIndex += 4;
}
} else {
for (int i = intCount; i > 0; i--) {
hashCode = 31 * hashCode + swapInt(buffer.getInt(arrayIndex));
arrayIndex += 4;
}
}
for (int i = byteCount; i > 0; i--) {
hashCode = 31 * hashCode + buffer.getByte(arrayIndex++);
}
if (hashCode == 0) {
hashCode = 1;
}
return hashCode;
}
/**
* Returns {@code true} if and only if the two specified buffers are identical
* to each other as described in {@code ChannelBuffer#equals(Object)}. This
* method is useful when implementing a new buffer type.
*/
public static boolean equals(ByteBuf bufferA, ByteBuf bufferB) {
final int aLen = bufferA.readableBytes();
if (aLen != bufferB.readableBytes()) {
return false;
}
final int longCount = aLen >>> 3;
final int byteCount = aLen & 7;
int aIndex = bufferA.readerIndex();
int bIndex = bufferB.readerIndex();
if (bufferA.order() == bufferB.order()) {
for (int i = longCount; i > 0; i--) {
if (bufferA.getLong(aIndex) != bufferB.getLong(bIndex)) {
return false;
}
aIndex += 8;
bIndex += 8;
}
} else {
for (int i = longCount; i > 0; i--) {
if (bufferA.getLong(aIndex) != swapLong(bufferB.getLong(bIndex))) {
return false;
}
aIndex += 8;
bIndex += 8;
}
}
for (int i = byteCount; i > 0; i--) {
if (bufferA.getByte(aIndex) != bufferB.getByte(bIndex)) {
return false;
}
aIndex++;
bIndex++;
}
return true;
}
/**
* Compares the two specified buffers as described in
* {@link ByteBuf#compareTo(ByteBuf)}. This method is useful when implementing a
* new buffer type.
*/
public static int compare(ByteBuf bufferA, ByteBuf bufferB) {
final int aLen = bufferA.readableBytes();
final int bLen = bufferB.readableBytes();
final int minLength = Math.min(aLen, bLen);
final int uintCount = minLength >>> 2;
final int byteCount = minLength & 3;
int aIndex = bufferA.readerIndex();
int bIndex = bufferB.readerIndex();
if (uintCount > 0) {
boolean bufferAIsBigEndian = bufferA.order() == ByteOrder.BIG_ENDIAN;
final long res;
int uintCountIncrement = uintCount << 2;
if (bufferA.order() == bufferB.order()) {
res = bufferAIsBigEndian ? compareUintBigEndian(bufferA, bufferB, aIndex, bIndex, uintCountIncrement)
: compareUintLittleEndian(bufferA, bufferB, aIndex, bIndex, uintCountIncrement);
} else {
res = bufferAIsBigEndian ? compareUintBigEndianA(bufferA, bufferB, aIndex, bIndex, uintCountIncrement)
: compareUintBigEndianB(bufferA, bufferB, aIndex, bIndex, uintCountIncrement);
}
if (res != 0) {
// Ensure we not overflow when cast
return (int) Math.min(Integer.MAX_VALUE, Math.max(Integer.MIN_VALUE, res));
}
aIndex += uintCountIncrement;
bIndex += uintCountIncrement;
}
for (int aEnd = aIndex + byteCount; aIndex < aEnd; ++aIndex, ++bIndex) {
int comp = bufferA.getUnsignedByte(aIndex) - bufferB.getUnsignedByte(bIndex);
if (comp != 0) {
return comp;
}
}
return aLen - bLen;
}
private static long compareUintBigEndian(ByteBuf bufferA, ByteBuf bufferB, int aIndex, int bIndex,
int uintCountIncrement) {
for (int aEnd = aIndex + uintCountIncrement; aIndex < aEnd; aIndex += 4, bIndex += 4) {
long comp = bufferA.getUnsignedInt(aIndex) - bufferB.getUnsignedInt(bIndex);
if (comp != 0) {
return comp;
}
}
return 0;
}
private static long compareUintLittleEndian(ByteBuf bufferA, ByteBuf bufferB, int aIndex, int bIndex,
int uintCountIncrement) {
for (int aEnd = aIndex + uintCountIncrement; aIndex < aEnd; aIndex += 4, bIndex += 4) {
long comp = (swapInt(bufferA.getInt(aIndex)) & 0xFFFFFFFFL)
- (swapInt(bufferB.getInt(bIndex)) & 0xFFFFFFFFL);
if (comp != 0) {
return comp;
}
}
return 0;
}
private static long compareUintBigEndianA(ByteBuf bufferA, ByteBuf bufferB, int aIndex, int bIndex,
int uintCountIncrement) {
for (int aEnd = aIndex + uintCountIncrement; aIndex < aEnd; aIndex += 4, bIndex += 4) {
long comp = bufferA.getUnsignedInt(aIndex) - (swapInt(bufferB.getInt(bIndex)) & 0xFFFFFFFFL);
if (comp != 0) {
return comp;
}
}
return 0;
}
private static long compareUintBigEndianB(ByteBuf bufferA, ByteBuf bufferB, int aIndex, int bIndex,
int uintCountIncrement) {
for (int aEnd = aIndex + uintCountIncrement; aIndex < aEnd; aIndex += 4, bIndex += 4) {
long comp = (swapInt(bufferA.getInt(aIndex)) & 0xFFFFFFFFL) - bufferB.getUnsignedInt(bIndex);
if (comp != 0) {
return comp;
}
}
return 0;
}
/**
* The default implementation of {@link ByteBuf#indexOf(int, int, byte)}. This
* method is useful when implementing a new buffer type.
*/
public static int indexOf(ByteBuf buffer, int fromIndex, int toIndex, byte value) {
if (fromIndex <= toIndex) {
return firstIndexOf(buffer, fromIndex, toIndex, value);
} else {
return lastIndexOf(buffer, fromIndex, toIndex, value);
}
}
/**
* Toggles the endianness of the specified 16-bit short integer.
*/
public static short swapShort(short value) {
return Short.reverseBytes(value);
}
/**
* Toggles the endianness of the specified 24-bit medium integer.
*/
public static int swapMedium(int value) {
int swapped = value << 16 & 0xff0000 | value & 0xff00 | value >>> 16 & 0xff;
if ((swapped & 0x800000) != 0) {
swapped |= 0xff000000;
}
return swapped;
}
/**
* Toggles the endianness of the specified 32-bit integer.
*/
public static int swapInt(int value) {
return Integer.reverseBytes(value);
}
/**
* Toggles the endianness of the specified 64-bit long integer.
*/
public static long swapLong(long value) {
return Long.reverseBytes(value);
}
/**
* Read the given amount of bytes into a new {@link ByteBuf} that is allocated
* from the {@link ByteBufAllocator}.
*/
public static ByteBuf readBytes(ByteBuf buffer, int length) {
ByteBuf dst = Unpooled.buffer(length);
buffer.readBytes(dst);
return dst;
}
private static int firstIndexOf(ByteBuf buffer, int fromIndex, int toIndex, byte value) {
fromIndex = Math.max(fromIndex, 0);
if (fromIndex >= toIndex || buffer.capacity() == 0) {
return -1;
}
for(int i = fromIndex; i < toIndex; ++i) {
if(buffer.getByte(i) == value) {
return i;
}
}
return -1;
}
private static int lastIndexOf(ByteBuf buffer, int fromIndex, int toIndex, byte value) {
fromIndex = Math.min(fromIndex, buffer.capacity());
if (fromIndex < 0 || buffer.capacity() == 0) {
return -1;
}
for(int i = fromIndex; i > toIndex; --i) {
if(buffer.getByte(i) == value) {
return i;
}
}
return -1;
}
/**
* Encode a {@link CharSequence} in
* <a href="http://en.wikipedia.org/wiki/UTF-8">UTF-8</a> and write it to a
* {@link ByteBuf} allocated with {@code alloc}.
*
* @param alloc The allocator used to allocate a new {@link ByteBuf}.
* @param seq The characters to write into a buffer.
* @return The {@link ByteBuf} which contains the
* <a href="http://en.wikipedia.org/wiki/UTF-8">UTF-8</a> encoded
* result.
*/
public static ByteBuf writeUtf8(CharSequence seq) {
// UTF-8 uses max. 3 bytes per char, so calculate the worst case.
ByteBuf buf = Unpooled.buffer(seq.length() * MAX_BYTES_PER_CHAR_UTF8);
writeUtf8(buf, seq);
return buf;
}
/**
* Encode a {@link CharSequence} in
* <a href="http://en.wikipedia.org/wiki/UTF-8">UTF-8</a> and write it to a
* {@link ByteBuf}.
*
* This method returns the actual number of bytes written.
*/
public static int writeUtf8(ByteBuf buf, CharSequence seq) {
final int len = seq.length();
buf.ensureWritable(len * MAX_BYTES_PER_CHAR_UTF8);
byte[] bytes = seq.toString().getBytes(StandardCharsets.UTF_8);
buf.writeBytes(bytes);
return bytes.length;
}
// Fast-Path implementation
private static int writeUtf8(AbstractByteBuf buffer, CharSequence seq, int len) {
int oldWriterIndex = buffer.writerIndex;
int writerIndex = oldWriterIndex;
// We can use the _set methods as these not need to do any index checks and
// reference checks.
// This is possible as we called ensureWritable(...) before.
for (int i = 0; i < len; i++) {
char c = seq.charAt(i);
if (c < 0x80) {
buffer._setByte(writerIndex++, (byte) c);
} else if (c < 0x800) {
buffer._setByte(writerIndex++, (byte) (0xc0 | (c >> 6)));
buffer._setByte(writerIndex++, (byte) (0x80 | (c & 0x3f)));
} else if (c >= '\uD800' && c <= '\uDFFF') { // isSurrogate(c)
if (!Character.isHighSurrogate(c)) {
buffer._setByte(writerIndex++, WRITE_UTF_UNKNOWN);
continue;
}
final char c2;
try {
// Surrogate Pair consumes 2 characters. Optimistically try to get the next
// character to avoid
// duplicate bounds checking with charAt. If an IndexOutOfBoundsException is
// thrown we will
// re-throw a more informative exception describing the problem.
c2 = seq.charAt(++i);
} catch (IndexOutOfBoundsException e) {
buffer._setByte(writerIndex++, WRITE_UTF_UNKNOWN);
break;
}
if (!Character.isLowSurrogate(c2)) {
buffer._setByte(writerIndex++, WRITE_UTF_UNKNOWN);
buffer._setByte(writerIndex++, Character.isHighSurrogate(c2) ? WRITE_UTF_UNKNOWN : c2);
continue;
}
int codePoint = Character.toCodePoint(c, c2);
// See http://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G2630.
buffer._setByte(writerIndex++, (byte) (0xf0 | (codePoint >> 18)));
buffer._setByte(writerIndex++, (byte) (0x80 | ((codePoint >> 12) & 0x3f)));
buffer._setByte(writerIndex++, (byte) (0x80 | ((codePoint >> 6) & 0x3f)));
buffer._setByte(writerIndex++, (byte) (0x80 | (codePoint & 0x3f)));
} else {
buffer._setByte(writerIndex++, (byte) (0xe0 | (c >> 12)));
buffer._setByte(writerIndex++, (byte) (0x80 | ((c >> 6) & 0x3f)));
buffer._setByte(writerIndex++, (byte) (0x80 | (c & 0x3f)));
}
}
// update the writerIndex without any extra checks for performance reasons
buffer.writerIndex = writerIndex;
return writerIndex - oldWriterIndex;
}
/**
* Encode the given {@link CharBuffer} using the given {@link Charset} into a
* new {@link ByteBuf} which is allocated via the {@link ByteBufAllocator}.
*/
public static ByteBuf encodeString(CharBuffer src, Charset charset) {
return encodeString0(false, src, charset);
}
static ByteBuf encodeString0(boolean enforceHeap, CharBuffer src, Charset charset) {
final CharsetEncoder encoder = charset.newEncoder();
int length = (int) ((double) src.remaining() * encoder.maxBytesPerChar());
final ByteBuf dst = Unpooled.buffer(length);
try {
final ByteBuffer dstBuf = dst.internalNioBuffer(dst.readerIndex(), length);
final int pos = dstBuf.position();
CoderResult cr = encoder.encode(src, dstBuf, true);
if (!cr.isUnderflow()) {
cr.throwException();
}
cr = encoder.flush(dstBuf);
if (!cr.isUnderflow()) {
cr.throwException();
}
dst.writerIndex(dst.writerIndex() + dstBuf.position() - pos);
return dst;
} catch (CharacterCodingException x) {
throw new IllegalStateException(x);
}
}
static String decodeString(ByteBuf src, int readerIndex, int len, Charset charset) {
if (len == 0) {
return "";
}
final CharsetDecoder decoder = charset.newDecoder();
final int maxLength = (int) ((double) len * decoder.maxCharsPerByte());
CharBuffer dst = CharBuffer.wrap(new char[maxLength]);
decodeString(decoder, src.nioBuffer(readerIndex, len), dst);
return dst.flip().toString();
}
private static void decodeString(CharsetDecoder decoder, ByteBuffer src, CharBuffer dst) {
try {
CoderResult cr = decoder.decode(src, dst, true);
if (!cr.isUnderflow()) {
cr.throwException();
}
cr = decoder.flush(dst);
if (!cr.isUnderflow()) {
cr.throwException();
}
} catch (CharacterCodingException x) {
throw new IllegalStateException(x);
}
}
/**
* Returns {@code true} if the given {@link ByteBuf} is valid text using the
* given {@link Charset}, otherwise return {@code false}.
*
* @param buf The given {@link ByteBuf}.
* @param charset The specified {@link Charset}.
*/
public static boolean isText(ByteBuf buf, Charset charset) {
return isText(buf, buf.readerIndex(), buf.readableBytes(), charset);
}
/**
* Returns {@code true} if the specified {@link ByteBuf} starting at
* {@code index} with {@code length} is valid text using the given
* {@link Charset}, otherwise return {@code false}.
*
* @param buf The given {@link ByteBuf}.
* @param index The start index of the specified buffer.
* @param length The length of the specified buffer.
* @param charset The specified {@link Charset}.
*
* @throws IndexOutOfBoundsException if {@code index} + {@code length} is
* greater than {@code buf.readableBytes}
*/
public static boolean isText(ByteBuf buf, int index, int length, Charset charset) {
checkNotNull(buf, "buf");
checkNotNull(charset, "charset");
final int maxIndex = buf.readerIndex() + buf.readableBytes();
if (index < 0 || length < 0 || index > maxIndex - length) {
throw new IndexOutOfBoundsException("index: " + index + " length: " + length);
}
return isUtf8(buf, index, length);
}
/**
* Returns {@code true} if the specified {@link ByteBuf} starting at
* {@code index} with {@code length} is valid UTF8 text, otherwise return
* {@code false}.
*
* @param buf The given {@link ByteBuf}.
* @param index The start index of the specified buffer.
* @param length The length of the specified buffer.
*
* @see <a href=http://www.ietf.org/rfc/rfc3629.txt>UTF-8 Definition</a>
*
* <pre>
* 1. Bytes format of UTF-8
*
* The table below summarizes the format of these different octet types.
* The letter x indicates bits available for encoding bits of the character number.
*
* Char. number range | UTF-8 octet sequence
* (hexadecimal) | (binary)
* --------------------+---------------------------------------------
* 0000 0000-0000 007F | 0xxxxxxx
* 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
* 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
* 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
* </pre>
*
* <pre>
* 2. Syntax of UTF-8 Byte Sequences
*
* UTF8-octets = *( UTF8-char )
* UTF8-char = UTF8-1 / UTF8-2 / UTF8-3 / UTF8-4
* UTF8-1 = %x00-7F
* UTF8-2 = %xC2-DF UTF8-tail
* UTF8-3 = %xE0 %xA0-BF UTF8-tail /
* %xE1-EC 2( UTF8-tail ) /
* %xED %x80-9F UTF8-tail /
* %xEE-EF 2( UTF8-tail )
* UTF8-4 = %xF0 %x90-BF 2( UTF8-tail ) /
* %xF1-F3 3( UTF8-tail ) /
* %xF4 %x80-8F 2( UTF8-tail )
* UTF8-tail = %x80-BF
* </pre>
*/
private static boolean isUtf8(ByteBuf buf, int index, int length) {
final int endIndex = index + length;
while (index < endIndex) {
byte b1 = buf.getByte(index++);
byte b2, b3, b4;
if ((b1 & 0x80) == 0) {
// 1 byte
continue;
}
if ((b1 & 0xE0) == 0xC0) {
// 2 bytes
//
// Bit/Byte pattern
// 110xxxxx 10xxxxxx
// C2..DF 80..BF
if (index >= endIndex) { // no enough bytes
return false;
}
b2 = buf.getByte(index++);
if ((b2 & 0xC0) != 0x80) { // 2nd byte not starts with 10
return false;
}
if ((b1 & 0xFF) < 0xC2) { // out of lower bound
return false;
}
} else if ((b1 & 0xF0) == 0xE0) {
// 3 bytes
//
// Bit/Byte pattern
// 1110xxxx 10xxxxxx 10xxxxxx
// E0 A0..BF 80..BF
// E1..EC 80..BF 80..BF
// ED 80..9F 80..BF
// E1..EF 80..BF 80..BF
if (index > endIndex - 2) { // no enough bytes
return false;
}
b2 = buf.getByte(index++);
b3 = buf.getByte(index++);
if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) { // 2nd or 3rd bytes not start with 10
return false;
}
if ((b1 & 0x0F) == 0x00 && (b2 & 0xFF) < 0xA0) { // out of lower bound
return false;
}
if ((b1 & 0x0F) == 0x0D && (b2 & 0xFF) > 0x9F) { // out of upper bound
return false;
}
} else if ((b1 & 0xF8) == 0xF0) {
// 4 bytes
//
// Bit/Byte pattern
// 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
// F0 90..BF 80..BF 80..BF
// F1..F3 80..BF 80..BF 80..BF
// F4 80..8F 80..BF 80..BF
if (index > endIndex - 3) { // no enough bytes
return false;
}
b2 = buf.getByte(index++);
b3 = buf.getByte(index++);
b4 = buf.getByte(index++);
if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80 || (b4 & 0xC0) != 0x80) {
// 2nd, 3rd or 4th bytes not start with 10
return false;
}
if ((b1 & 0xFF) > 0xF4 // b1 invalid
|| (b1 & 0xFF) == 0xF0 && (b2 & 0xFF) < 0x90 // b2 out of lower bound
|| (b1 & 0xFF) == 0xF4 && (b2 & 0xFF) > 0x8F) { // b2 out of upper bound
return false;
}
} else {
return false;
}
}
return true;
}
private ByteBufUtil() {
}
}

View File

@ -0,0 +1,106 @@
/*
* Copyright 2015 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License, version 2.0 (the
* "License"); you may not use this file except in compliance with the License. You may obtain a
* copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package net.lax1dude.eaglercraft.v1_8.netty;
/**
* Math utility methods.
*/
public final class MathUtil {
private MathUtil() {
}
/**
* Fast method of finding the next power of 2 greater than or equal to the
* supplied value.
*
* <p>
* If the value is {@code <= 0} then 1 will be returned. This method is not
* suitable for {@link Integer#MIN_VALUE} or numbers greater than 2^30.
*
* @param value from which to search for next power of 2
* @return The next power of 2 or the value itself if it is a power of 2
*/
public static int findNextPositivePowerOfTwo(final int value) {
assert value > Integer.MIN_VALUE && value < 0x40000000;
return 1 << (32 - Integer.numberOfLeadingZeros(value - 1));
}
/**
* Fast method of finding the next power of 2 greater than or equal to the
* supplied value.
* <p>
* This method will do runtime bounds checking and call
* {@link #findNextPositivePowerOfTwo(int)} if within a valid range.
*
* @param value from which to search for next power of 2
* @return The next power of 2 or the value itself if it is a power of 2.
* <p>
* Special cases for return values are as follows:
* <ul>
* <li>{@code <= 0} -> 1</li>
* <li>{@code >= 2^30} -> 2^30</li>
* </ul>
*/
public static int safeFindNextPositivePowerOfTwo(final int value) {
return value <= 0 ? 1 : value >= 0x40000000 ? 0x40000000 : findNextPositivePowerOfTwo(value);
}
/**
* Determine if the requested {@code index} and {@code length} will fit within
* {@code capacity}.
*
* @param index The starting index.
* @param length The length which will be utilized (starting from
* {@code index}).
* @param capacity The capacity that {@code index + length} is allowed to be
* within.
* @return {@code false} if the requested {@code index} and {@code length} will
* fit within {@code capacity}. {@code true} if this would result in an
* index out of bounds exception.
*/
public static boolean isOutOfBounds(int index, int length, int capacity) {
return (index | length | capacity | (index + length) | (capacity - (index + length))) < 0;
}
/**
* Compares two {@code int} values.
*
* @param x the first {@code int} to compare
* @param y the second {@code int} to compare
* @return the value {@code 0} if {@code x == y}; {@code -1} if {@code x < y};
* and {@code 1} if {@code x > y}
*/
public static int compare(final int x, final int y) {
// do not subtract for comparison, it could overflow
return x < y ? -1 : (x > y ? 1 : 0);
}
/**
* Compare two {@code long} values.
*
* @param x the first {@code long} to compare.
* @param y the second {@code long} to compare.
* @return
* <ul>
* <li>0 if {@code x == y}</li>
* <li>{@code > 0} if {@code x > y}</li>
* <li>{@code < 0} if {@code x < y}</li>
* </ul>
*/
public static int compare(long x, long y) {
return (x < y) ? -1 : (x > y) ? 1 : 0;
}
}

View File

@ -0,0 +1,44 @@
package net.lax1dude.eaglercraft.v1_8.netty;
import java.nio.ByteBuffer;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.IntBuffer;
public class NioBufferFunctions {
public static final void get(ByteBuffer src, int index, byte[] dst, int dstOffset, int length) {
for(int i = 0; i < length; ++i) {
dst[i + dstOffset] = src.get(i + index);
}
}
public static final void put(ByteBuffer dst, int dstIndex, ByteBuffer src, int srcOffset, int length) {
for(int i = 0; i < length; ++i) {
dst.put(i + dstIndex, src.get(i + srcOffset));
}
}
public static final void put(ByteBuffer dst, int dstIndex, byte[] src, int srcOffset, int length) {
for(int i = 0; i < length; ++i) {
dst.put(i + dstIndex, src[i + srcOffset]);
}
}
public static final void get(ByteBuffer src, int index, byte[] dst) {
get(src, index, dst, 0, dst.length);
}
public static void put(ByteBuffer newBuffer, ByteBuffer flip) {
int len = flip.remaining();
for(int i = 0; i < len; ++i) {
newBuffer.put(flip.get());
}
}
public static void put(IntBuffer intBuffer, int index, int[] data) {
int p = intBuffer.position();
intBuffer.position(index);
intBuffer.put(data);
intBuffer.position(p);
}
}

View File

@ -0,0 +1,329 @@
/*
* Copyright 2014 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License, version 2.0 (the
* "License"); you may not use this file except in compliance with the License. You may obtain a
* copy of the License at:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package net.lax1dude.eaglercraft.v1_8.netty;
import java.util.Collection;
import java.util.Map;
/**
* A grab-bag of useful utility methods.
*/
public final class ObjectUtil {
private static final float FLOAT_ZERO = 0.0F;
private static final double DOUBLE_ZERO = 0.0D;
private static final long LONG_ZERO = 0L;
private static final int INT_ZERO = 0;
private ObjectUtil() {
}
/**
* Checks that the given argument is not null. If it is, throws
* {@link NullPointerException}. Otherwise, returns the argument.
*/
public static <T> T checkNotNull(T arg, String text) {
if (arg == null) {
throw new NullPointerException(text);
}
return arg;
}
/**
* Check that the given varargs is not null and does not contain elements null
* elements.
*
* If it is, throws {@link NullPointerException}. Otherwise, returns the
* argument.
*/
public static <T> T[] deepCheckNotNull(String text, T... varargs) {
if (varargs == null) {
throw new NullPointerException(text);
}
for (T element : varargs) {
if (element == null) {
throw new NullPointerException(text);
}
}
return varargs;
}
/**
* Checks that the given argument is not null. If it is, throws
* {@link IllegalArgumentException}. Otherwise, returns the argument.
*/
public static <T> T checkNotNullWithIAE(final T arg, final String paramName) throws IllegalArgumentException {
if (arg == null) {
throw new IllegalArgumentException("Param '" + paramName + "' must not be null");
}
return arg;
}
/**
* Checks that the given argument is not null. If it is, throws
* {@link IllegalArgumentException}. Otherwise, returns the argument.
*
* @param <T> type of the given argument value.
* @param name of the parameter, belongs to the exception message.
* @param index of the array, belongs to the exception message.
* @param value to check.
* @return the given argument value.
* @throws IllegalArgumentException if value is null.
*/
public static <T> T checkNotNullArrayParam(T value, int index, String name) throws IllegalArgumentException {
if (value == null) {
throw new IllegalArgumentException(
"Array index " + index + " of parameter '" + name + "' must not be null");
}
return value;
}
/**
* Checks that the given argument is strictly positive. If it is not, throws
* {@link IllegalArgumentException}. Otherwise, returns the argument.
*/
public static int checkPositive(int i, String name) {
if (i <= INT_ZERO) {
throw new IllegalArgumentException(name + " : " + i + " (expected: > 0)");
}
return i;
}
/**
* Checks that the given argument is strictly positive. If it is not, throws
* {@link IllegalArgumentException}. Otherwise, returns the argument.
*/
public static long checkPositive(long l, String name) {
if (l <= LONG_ZERO) {
throw new IllegalArgumentException(name + " : " + l + " (expected: > 0)");
}
return l;
}
/**
* Checks that the given argument is strictly positive. If it is not, throws
* {@link IllegalArgumentException}. Otherwise, returns the argument.
*/
public static double checkPositive(final double d, final String name) {
if (d <= DOUBLE_ZERO) {
throw new IllegalArgumentException(name + " : " + d + " (expected: > 0)");
}
return d;
}
/**
* Checks that the given argument is strictly positive. If it is not, throws
* {@link IllegalArgumentException}. Otherwise, returns the argument.
*/
public static float checkPositive(final float f, final String name) {
if (f <= FLOAT_ZERO) {
throw new IllegalArgumentException(name + " : " + f + " (expected: > 0)");
}
return f;
}
/**
* Checks that the given argument is positive or zero. If it is not , throws
* {@link IllegalArgumentException}. Otherwise, returns the argument.
*/
public static int checkPositiveOrZero(int i, String name) {
if (i < INT_ZERO) {
throw new IllegalArgumentException(name + " : " + i + " (expected: >= 0)");
}
return i;
}
/**
* Checks that the given argument is positive or zero. If it is not, throws
* {@link IllegalArgumentException}. Otherwise, returns the argument.
*/
public static long checkPositiveOrZero(long l, String name) {
if (l < LONG_ZERO) {
throw new IllegalArgumentException(name + " : " + l + " (expected: >= 0)");
}
return l;
}
/**
* Checks that the given argument is positive or zero. If it is not, throws
* {@link IllegalArgumentException}. Otherwise, returns the argument.
*/
public static double checkPositiveOrZero(final double d, final String name) {
if (d < DOUBLE_ZERO) {
throw new IllegalArgumentException(name + " : " + d + " (expected: >= 0)");
}
return d;
}
/**
* Checks that the given argument is positive or zero. If it is not, throws
* {@link IllegalArgumentException}. Otherwise, returns the argument.
*/
public static float checkPositiveOrZero(final float f, final String name) {
if (f < FLOAT_ZERO) {
throw new IllegalArgumentException(name + " : " + f + " (expected: >= 0)");
}
return f;
}
/**
* Checks that the given argument is in range. If it is not, throws
* {@link IllegalArgumentException}. Otherwise, returns the argument.
*/
public static int checkInRange(int i, int start, int end, String name) {
if (i < start || i > end) {
throw new IllegalArgumentException(name + ": " + i + " (expected: " + start + "-" + end + ")");
}
return i;
}
/**
* Checks that the given argument is in range. If it is not, throws
* {@link IllegalArgumentException}. Otherwise, returns the argument.
*/
public static long checkInRange(long l, long start, long end, String name) {
if (l < start || l > end) {
throw new IllegalArgumentException(name + ": " + l + " (expected: " + start + "-" + end + ")");
}
return l;
}
/**
* Checks that the given argument is neither null nor empty. If it is, throws
* {@link NullPointerException} or {@link IllegalArgumentException}. Otherwise,
* returns the argument.
*/
public static <T> T[] checkNonEmpty(T[] array, String name) {
// No String concatenation for check
if (checkNotNull(array, name).length == 0) {
throw new IllegalArgumentException("Param '" + name + "' must not be empty");
}
return array;
}
/**
* Checks that the given argument is neither null nor empty. If it is, throws
* {@link NullPointerException} or {@link IllegalArgumentException}. Otherwise,
* returns the argument.
*/
public static byte[] checkNonEmpty(byte[] array, String name) {
// No String concatenation for check
if (checkNotNull(array, name).length == 0) {
throw new IllegalArgumentException("Param '" + name + "' must not be empty");
}
return array;
}
/**
* Checks that the given argument is neither null nor empty. If it is, throws
* {@link NullPointerException} or {@link IllegalArgumentException}. Otherwise,
* returns the argument.
*/
public static char[] checkNonEmpty(char[] array, String name) {
// No String concatenation for check
if (checkNotNull(array, name).length == 0) {
throw new IllegalArgumentException("Param '" + name + "' must not be empty");
}
return array;
}
/**
* Checks that the given argument is neither null nor empty. If it is, throws
* {@link NullPointerException} or {@link IllegalArgumentException}. Otherwise,
* returns the argument.
*/
public static <T extends Collection<?>> T checkNonEmpty(T collection, String name) {
// No String concatenation for check
if (checkNotNull(collection, name).isEmpty()) {
throw new IllegalArgumentException("Param '" + name + "' must not be empty");
}
return collection;
}
/**
* Checks that the given argument is neither null nor empty. If it is, throws
* {@link NullPointerException} or {@link IllegalArgumentException}. Otherwise,
* returns the argument.
*/
public static String checkNonEmpty(final String value, final String name) {
if (checkNotNull(value, name).isEmpty()) {
throw new IllegalArgumentException("Param '" + name + "' must not be empty");
}
return value;
}
/**
* Checks that the given argument is neither null nor empty. If it is, throws
* {@link NullPointerException} or {@link IllegalArgumentException}. Otherwise,
* returns the argument.
*/
public static <K, V, T extends Map<K, V>> T checkNonEmpty(T value, String name) {
if (checkNotNull(value, name).isEmpty()) {
throw new IllegalArgumentException("Param '" + name + "' must not be empty");
}
return value;
}
/**
* Checks that the given argument is neither null nor empty. If it is, throws
* {@link NullPointerException} or {@link IllegalArgumentException}. Otherwise,
* returns the argument.
*/
public static CharSequence checkNonEmpty(final CharSequence value, final String name) {
if (checkNotNull(value, name).length() == 0) {
throw new IllegalArgumentException("Param '" + name + "' must not be empty");
}
return value;
}
/**
* Trims the given argument and checks whether it is neither null nor empty. If
* it is, throws {@link NullPointerException} or
* {@link IllegalArgumentException}. Otherwise, returns the trimmed argument.
*
* @param value to trim and check.
* @param name of the parameter.
* @return the trimmed (not the original) value.
* @throws NullPointerException if value is null.
* @throws IllegalArgumentException if the trimmed value is empty.
*/
public static String checkNonEmptyAfterTrim(final String value, final String name) {
String trimmed = checkNotNull(value, name).trim();
return checkNonEmpty(trimmed, name);
}
/**
* Resolves a possibly null Integer to a primitive int, using a default value.
*
* @param wrapper the wrapper
* @param defaultValue the default value
* @return the primitive value
*/
public static int intValue(Integer wrapper, int defaultValue) {
return wrapper != null ? wrapper : defaultValue;
}
/**
* Resolves a possibly null Long to a primitive long, using a default value.
*
* @param wrapper the wrapper
* @param defaultValue the default value
* @return the primitive value
*/
public static long longValue(Long wrapper, long defaultValue) {
return wrapper != null ? wrapper : defaultValue;
}
}

View File

@ -0,0 +1,778 @@
/*
* Copyright 2012 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package net.lax1dude.eaglercraft.v1_8.netty;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.Charset;
/**
* Wrapper which swap the {@link ByteOrder} of a {@link ByteBuf}.
*/
public class SwappedByteBuf extends ByteBuf {
private final ByteBuf buf;
private final ByteOrder order;
public SwappedByteBuf(ByteBuf buf) {
if (buf == null) {
throw new NullPointerException("buf");
}
this.buf = buf;
if (buf.order() == ByteOrder.BIG_ENDIAN) {
order = ByteOrder.LITTLE_ENDIAN;
} else {
order = ByteOrder.BIG_ENDIAN;
}
}
@Override
public ByteOrder order() {
return order;
}
@Override
public ByteBuf order(ByteOrder endianness) {
if (endianness == null) {
throw new NullPointerException("endianness");
}
if (endianness == order) {
return this;
}
return buf;
}
@Override
public ByteBuf unwrap() {
return buf;
}
@Override
public int capacity() {
return buf.capacity();
}
@Override
public ByteBuf capacity(int newCapacity) {
buf.capacity(newCapacity);
return this;
}
@Override
public int maxCapacity() {
return buf.maxCapacity();
}
@Override
public boolean isDirect() {
return buf.isDirect();
}
@Override
public int readerIndex() {
return buf.readerIndex();
}
@Override
public ByteBuf readerIndex(int readerIndex) {
buf.readerIndex(readerIndex);
return this;
}
@Override
public int writerIndex() {
return buf.writerIndex();
}
@Override
public ByteBuf writerIndex(int writerIndex) {
buf.writerIndex(writerIndex);
return this;
}
@Override
public ByteBuf setIndex(int readerIndex, int writerIndex) {
buf.setIndex(readerIndex, writerIndex);
return this;
}
@Override
public int readableBytes() {
return buf.readableBytes();
}
@Override
public int writableBytes() {
return buf.writableBytes();
}
@Override
public int maxWritableBytes() {
return buf.maxWritableBytes();
}
@Override
public boolean isReadable() {
return buf.isReadable();
}
@Override
public boolean isReadable(int size) {
return buf.isReadable(size);
}
@Override
public boolean isWritable() {
return buf.isWritable();
}
@Override
public boolean isWritable(int size) {
return buf.isWritable(size);
}
@Override
public ByteBuf clear() {
buf.clear();
return this;
}
@Override
public ByteBuf markReaderIndex() {
buf.markReaderIndex();
return this;
}
@Override
public ByteBuf resetReaderIndex() {
buf.resetReaderIndex();
return this;
}
@Override
public ByteBuf markWriterIndex() {
buf.markWriterIndex();
return this;
}
@Override
public ByteBuf resetWriterIndex() {
buf.resetWriterIndex();
return this;
}
@Override
public ByteBuf discardReadBytes() {
buf.discardReadBytes();
return this;
}
@Override
public ByteBuf discardSomeReadBytes() {
buf.discardSomeReadBytes();
return this;
}
@Override
public ByteBuf ensureWritable(int writableBytes) {
buf.ensureWritable(writableBytes);
return this;
}
@Override
public int ensureWritable(int minWritableBytes, boolean force) {
return buf.ensureWritable(minWritableBytes, force);
}
@Override
public boolean getBoolean(int index) {
return buf.getBoolean(index);
}
@Override
public byte getByte(int index) {
return buf.getByte(index);
}
@Override
public short getUnsignedByte(int index) {
return buf.getUnsignedByte(index);
}
@Override
public short getShort(int index) {
return ByteBufUtil.swapShort(buf.getShort(index));
}
@Override
public int getUnsignedShort(int index) {
return getShort(index) & 0xFFFF;
}
@Override
public int getMedium(int index) {
return ByteBufUtil.swapMedium(buf.getMedium(index));
}
@Override
public int getUnsignedMedium(int index) {
return getMedium(index) & 0xFFFFFF;
}
@Override
public int getInt(int index) {
return ByteBufUtil.swapInt(buf.getInt(index));
}
@Override
public long getUnsignedInt(int index) {
return getInt(index) & 0xFFFFFFFFL;
}
@Override
public long getLong(int index) {
return ByteBufUtil.swapLong(buf.getLong(index));
}
@Override
public char getChar(int index) {
return (char) getShort(index);
}
@Override
public float getFloat(int index) {
return Float.intBitsToFloat(getInt(index));
}
@Override
public double getDouble(int index) {
return Double.longBitsToDouble(getLong(index));
}
@Override
public ByteBuf getBytes(int index, ByteBuf dst) {
buf.getBytes(index, dst);
return this;
}
@Override
public ByteBuf getBytes(int index, ByteBuf dst, int length) {
buf.getBytes(index, dst, length);
return this;
}
@Override
public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
buf.getBytes(index, dst, dstIndex, length);
return this;
}
@Override
public ByteBuf getBytes(int index, byte[] dst) {
buf.getBytes(index, dst);
return this;
}
@Override
public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
buf.getBytes(index, dst, dstIndex, length);
return this;
}
@Override
public ByteBuf getBytes(int index, ByteBuffer dst) {
buf.getBytes(index, dst);
return this;
}
@Override
public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
buf.getBytes(index, out, length);
return this;
}
@Override
public ByteBuf setBoolean(int index, boolean value) {
buf.setBoolean(index, value);
return this;
}
@Override
public ByteBuf setByte(int index, int value) {
buf.setByte(index, value);
return this;
}
@Override
public ByteBuf setShort(int index, int value) {
buf.setShort(index, ByteBufUtil.swapShort((short) value));
return this;
}
@Override
public ByteBuf setMedium(int index, int value) {
buf.setMedium(index, ByteBufUtil.swapMedium(value));
return this;
}
@Override
public ByteBuf setInt(int index, int value) {
buf.setInt(index, ByteBufUtil.swapInt(value));
return this;
}
@Override
public ByteBuf setLong(int index, long value) {
buf.setLong(index, ByteBufUtil.swapLong(value));
return this;
}
@Override
public ByteBuf setChar(int index, int value) {
setShort(index, value);
return this;
}
@Override
public ByteBuf setFloat(int index, float value) {
setInt(index, Float.floatToRawIntBits(value));
return this;
}
@Override
public ByteBuf setDouble(int index, double value) {
setLong(index, Double.doubleToRawLongBits(value));
return this;
}
@Override
public ByteBuf setBytes(int index, ByteBuf src) {
buf.setBytes(index, src);
return this;
}
@Override
public ByteBuf setBytes(int index, ByteBuf src, int length) {
buf.setBytes(index, src, length);
return this;
}
@Override
public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
buf.setBytes(index, src, srcIndex, length);
return this;
}
@Override
public ByteBuf setBytes(int index, byte[] src) {
buf.setBytes(index, src);
return this;
}
@Override
public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
buf.setBytes(index, src, srcIndex, length);
return this;
}
@Override
public ByteBuf setBytes(int index, ByteBuffer src) {
buf.setBytes(index, src);
return this;
}
@Override
public int setBytes(int index, InputStream in, int length) throws IOException {
return buf.setBytes(index, in, length);
}
@Override
public ByteBuf setZero(int index, int length) {
buf.setZero(index, length);
return this;
}
@Override
public boolean readBoolean() {
return buf.readBoolean();
}
@Override
public byte readByte() {
return buf.readByte();
}
@Override
public short readUnsignedByte() {
return buf.readUnsignedByte();
}
@Override
public short readShort() {
return ByteBufUtil.swapShort(buf.readShort());
}
@Override
public int readUnsignedShort() {
return readShort() & 0xFFFF;
}
@Override
public int readMedium() {
return ByteBufUtil.swapMedium(buf.readMedium());
}
@Override
public int readUnsignedMedium() {
return readMedium() & 0xFFFFFF;
}
@Override
public int readInt() {
return ByteBufUtil.swapInt(buf.readInt());
}
@Override
public long readUnsignedInt() {
return readInt() & 0xFFFFFFFFL;
}
@Override
public long readLong() {
return ByteBufUtil.swapLong(buf.readLong());
}
@Override
public char readChar() {
return (char) readShort();
}
@Override
public float readFloat() {
return Float.intBitsToFloat(readInt());
}
@Override
public double readDouble() {
return Double.longBitsToDouble(readLong());
}
@Override
public ByteBuf readBytes(int length) {
return buf.readBytes(length).order(order());
}
@Override
public ByteBuf readSlice(int length) {
return buf.readSlice(length).order(order);
}
@Override
public ByteBuf readBytes(ByteBuf dst) {
buf.readBytes(dst);
return this;
}
@Override
public ByteBuf readBytes(ByteBuf dst, int length) {
buf.readBytes(dst, length);
return this;
}
@Override
public ByteBuf readBytes(ByteBuf dst, int dstIndex, int length) {
buf.readBytes(dst, dstIndex, length);
return this;
}
@Override
public ByteBuf readBytes(byte[] dst) {
buf.readBytes(dst);
return this;
}
@Override
public ByteBuf readBytes(byte[] dst, int dstIndex, int length) {
buf.readBytes(dst, dstIndex, length);
return this;
}
@Override
public ByteBuf readBytes(ByteBuffer dst) {
buf.readBytes(dst);
return this;
}
@Override
public ByteBuf readBytes(OutputStream out, int length) throws IOException {
buf.readBytes(out, length);
return this;
}
@Override
public ByteBuf skipBytes(int length) {
buf.skipBytes(length);
return this;
}
@Override
public ByteBuf writeBoolean(boolean value) {
buf.writeBoolean(value);
return this;
}
@Override
public ByteBuf writeByte(int value) {
buf.writeByte(value);
return this;
}
@Override
public ByteBuf writeShort(int value) {
buf.writeShort(ByteBufUtil.swapShort((short) value));
return this;
}
@Override
public ByteBuf writeMedium(int value) {
buf.writeMedium(ByteBufUtil.swapMedium(value));
return this;
}
@Override
public ByteBuf writeInt(int value) {
buf.writeInt(ByteBufUtil.swapInt(value));
return this;
}
@Override
public ByteBuf writeLong(long value) {
buf.writeLong(ByteBufUtil.swapLong(value));
return this;
}
@Override
public ByteBuf writeChar(int value) {
writeShort(value);
return this;
}
@Override
public ByteBuf writeFloat(float value) {
writeInt(Float.floatToRawIntBits(value));
return this;
}
@Override
public ByteBuf writeDouble(double value) {
writeLong(Double.doubleToRawLongBits(value));
return this;
}
@Override
public ByteBuf writeBytes(ByteBuf src) {
buf.writeBytes(src);
return this;
}
@Override
public ByteBuf writeBytes(ByteBuf src, int length) {
buf.writeBytes(src, length);
return this;
}
@Override
public ByteBuf writeBytes(ByteBuf src, int srcIndex, int length) {
buf.writeBytes(src, srcIndex, length);
return this;
}
@Override
public ByteBuf writeBytes(byte[] src) {
buf.writeBytes(src);
return this;
}
@Override
public ByteBuf writeBytes(byte[] src, int srcIndex, int length) {
buf.writeBytes(src, srcIndex, length);
return this;
}
@Override
public ByteBuf writeBytes(ByteBuffer src) {
buf.writeBytes(src);
return this;
}
@Override
public int writeBytes(InputStream in, int length) throws IOException {
return buf.writeBytes(in, length);
}
@Override
public ByteBuf writeZero(int length) {
buf.writeZero(length);
return this;
}
@Override
public int indexOf(int fromIndex, int toIndex, byte value) {
return buf.indexOf(fromIndex, toIndex, value);
}
@Override
public int bytesBefore(byte value) {
return buf.bytesBefore(value);
}
@Override
public int bytesBefore(int length, byte value) {
return buf.bytesBefore(length, value);
}
@Override
public int bytesBefore(int index, int length, byte value) {
return buf.bytesBefore(index, length, value);
}
@Override
public ByteBuf copy() {
return buf.copy().order(order);
}
@Override
public ByteBuf copy(int index, int length) {
return buf.copy(index, length).order(order);
}
@Override
public ByteBuf slice() {
return buf.slice().order(order);
}
@Override
public ByteBuf slice(int index, int length) {
return buf.slice(index, length).order(order);
}
@Override
public ByteBuf duplicate() {
return buf.duplicate().order(order);
}
@Override
public int nioBufferCount() {
return buf.nioBufferCount();
}
@Override
public ByteBuffer nioBuffer() {
return buf.nioBuffer().order(order);
}
@Override
public ByteBuffer nioBuffer(int index, int length) {
return buf.nioBuffer(index, length).order(order);
}
@Override
public ByteBuffer internalNioBuffer(int index, int length) {
return nioBuffer(index, length);
}
@Override
public ByteBuffer[] nioBuffers() {
ByteBuffer[] nioBuffers = buf.nioBuffers();
for (int i = 0; i < nioBuffers.length; i++) {
nioBuffers[i] = nioBuffers[i].order(order);
}
return nioBuffers;
}
@Override
public ByteBuffer[] nioBuffers(int index, int length) {
ByteBuffer[] nioBuffers = buf.nioBuffers(index, length);
for (int i = 0; i < nioBuffers.length; i++) {
nioBuffers[i] = nioBuffers[i].order(order);
}
return nioBuffers;
}
@Override
public boolean hasArray() {
return buf.hasArray();
}
@Override
public byte[] array() {
return buf.array();
}
@Override
public int arrayOffset() {
return buf.arrayOffset();
}
@Override
public boolean hasMemoryAddress() {
return buf.hasMemoryAddress();
}
@Override
public long memoryAddress() {
return buf.memoryAddress();
}
@Override
public String toString(Charset charset) {
return buf.toString(charset);
}
@Override
public String toString(int index, int length, Charset charset) {
return buf.toString(index, length, charset);
}
@Override
public int hashCode() {
return buf.hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof ByteBuf) {
return ByteBufUtil.equals(this, (ByteBuf) obj);
}
return false;
}
@Override
public int compareTo(ByteBuf buffer) {
return ByteBufUtil.compare(this, buffer);
}
@Override
public String toString() {
return "Swapped(" + buf.toString() + ')';
}
}

View File

@ -0,0 +1,42 @@
package net.lax1dude.eaglercraft.v1_8.netty;
import java.nio.ByteBuffer;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class Unpooled {
public static final ByteBuf EMPTY_BUFFER = ByteBuf.allocate(0, 0);
public static ByteBuf buffer() {
return ByteBuf.allocate(256, Integer.MAX_VALUE);
}
public static ByteBuf buffer(int length) {
return ByteBuf.allocate(length, Integer.MAX_VALUE);
}
public static ByteBuf buffer(int length, int maxLength) {
return ByteBuf.allocate(length, maxLength);
}
public static ByteBuf buffer(ByteBuffer data, int maxLength) {
return ByteBuf.allocate(data, maxLength);
}
public static ByteBuf buffer(byte[] data, int maxLength) {
return ByteBuf.allocate(ByteBuffer.wrap(data), maxLength);
}
}