diff --git a/src/dorkbox/network/pipeline/ByteBufInput.java b/src/dorkbox/network/pipeline/ByteBufInput.java deleted file mode 100644 index 208d6381..00000000 --- a/src/dorkbox/network/pipeline/ByteBufInput.java +++ /dev/null @@ -1,977 +0,0 @@ -/* - * Copyright 2010 dorkbox, llc - * - * Licensed 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. - * - * Copyright (c) 2008, Nathan Sweet - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided with the distribution. - * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package dorkbox.network.pipeline; - -import java.io.DataInput; -import java.io.IOException; -import java.io.InputStream; - -import com.esotericsoftware.kryo.KryoException; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.util.Util; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; - -/** - * An {@link InputStream} which reads data from a {@link ByteBuf}. - *

- * 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. - *

- * 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. - *

- * Utility methods are provided for efficiently reading primitive types and strings. - *

- *

- *

- *

- * Modified from KRYO ByteBufferInput to use ByteBuf instead of ByteBuffer. - */ - -public -class ByteBufInput extends Input { - private ByteBuf byteBuf; - private int initialReaderIndex = 0; - private int initialWriterIndex = 0; - - private byte[] tempBuffer; - - /** Creates an uninitialized Input, {@link #setBuffer(ByteBuf)} must be called before the Input is used. */ - public ByteBufInput () { - } - - /** Creates a new Input for reading from a direct {@link ByteBuf}. - * @param bufferSize The size of the buffer. An exception is thrown if more bytes than this are read and - * {@link #fill(ByteBuf, int, int)} does not supply more bytes. */ - public ByteBufInput (int bufferSize) { - this.capacity = bufferSize; - byteBuf = Unpooled.buffer(bufferSize); - } - - /** Creates a new Input for reading from a {@link ByteBuf} which is filled with the specified bytes. */ - public ByteBufInput (byte[] bytes) { - this(bytes, 0, bytes.length); - } - - /** Creates a new Input for reading from a {@link ByteBuf} which is filled with the specified bytes. - * @see #setBuffer(byte[], int, int) */ - public ByteBufInput (byte[] bytes, int offset, int count) { - if (bytes == null) throw new IllegalArgumentException("bytes cannot be null."); - - setBuffer(Unpooled.wrappedBuffer(bytes, offset, count)); - } - - /** Creates a new Input for reading from a ByteBuffer. */ - public ByteBufInput (ByteBuf buffer) { - setBuffer(buffer); - } - - /** @see Input#Input(InputStream) */ - public ByteBufInput (InputStream inputStream) { - this(4096); - if (inputStream == null) throw new IllegalArgumentException("inputStream cannot be null."); - this.inputStream = inputStream; - } - - /** @see Input#Input(InputStream, int) */ - public ByteBufInput (InputStream inputStream, int bufferSize) { - this(bufferSize); - if (inputStream == null) throw new IllegalArgumentException("inputStream cannot be null."); - this.inputStream = inputStream; - } - - /** Throws {@link UnsupportedOperationException} because this input uses a ByteBuffer, not a byte[]. - * @deprecated - * @see #getByteBuf() */ - @Deprecated - public byte[] getBuffer () { - throw new UnsupportedOperationException("This input does not used a byte[], see #getByteBuf()."); - } - - /** Throws {@link UnsupportedOperationException} because this input uses a ByteBuffer, not a byte[]. - * @deprecated - * @see #setBuffer(ByteBuf) */ - @Deprecated - public void setBuffer (byte[] bytes) { - throw new UnsupportedOperationException("This input does not used a byte[], see #setByteBuf(ByteBuf)."); - } - - /** Throws {@link UnsupportedOperationException} because this input uses a ByteBuffer, not a byte[]. - * @deprecated - * @see #setBuffer(ByteBuf) */ - @Deprecated - public void setBuffer (byte[] bytes, int offset, int count) { - throw new UnsupportedOperationException("This input does not used a byte[], see #setByteBuf()."); - } - - /** Sets a new buffer to read from. The bytes are not copied, the old buffer is discarded and the new buffer used in its place. - * The position, limit, and capacity are set to match the specified buffer. The total is reset. The - * {@link #setInputStream(InputStream) InputStream} is set to null. */ - public void setBuffer(ByteBuf buffer) { - if (buffer == null) throw new IllegalArgumentException("buffer cannot be null."); - byteBuf = buffer; - - initialReaderIndex = byteBuf.readerIndex(); // where the object starts... - initialWriterIndex = byteBuf.writerIndex(); // where the object ends... - - position = initialReaderIndex; - limit = initialWriterIndex; - capacity = buffer.capacity(); - total = 0; - inputStream = null; - } - - public ByteBuf getByteBuf () { - return byteBuf; - } - - public void setInputStream (InputStream inputStream) { - this.inputStream = inputStream; - limit = 0; - reset(); - } - - public void reset () { - super.reset(); - - byteBuf.setIndex(initialReaderIndex, initialWriterIndex); - } - - /** Fills the buffer with more bytes. The default implementation reads from the {@link #getInputStream() InputStream}, if set. - * Can be overridden to fill the bytes from another source. */ - protected int fill (ByteBuf buffer, int offset, int count) throws KryoException { - if (inputStream == null) return -1; - try { - if (tempBuffer == null) tempBuffer = new byte[2048]; - buffer.readerIndex(offset); - int total = 0; - while (count > 0) { - int read = inputStream.read(tempBuffer, 0, Math.min(tempBuffer.length, count)); - if (read == -1) { - if (total == 0) return -1; - break; - } - buffer.writeBytes(tempBuffer, 0, read); - count -= read; - total += read; - } - buffer.readerIndex(offset); - return total; - } catch (IOException ex) { - throw new KryoException(ex); - } - } - - protected int require (int required) throws KryoException { - int remaining = limit - position; - if (remaining >= required) return remaining; - if (required > capacity) throw new KryoException("Buffer too small: capacity: " + capacity + ", required: " + required); - - int count; - // Try to fill the buffer. - if (remaining > 0) { - count = fill(byteBuf, limit, capacity - limit); - if (count == -1) throw new KryoException("Buffer underflow."); - remaining += count; - if (remaining >= required) { - limit += count; - return remaining; - } - } - - // Compact. Position after compaction can be non-zero. - // CANNOT COMPACT A BYTEBUF - // byteBuffer.position(position); - // byteBuffer.compact(); - // total += position; - // position = 0; - // - // while (true) { - // count = fill(byteBuffer, remaining, capacity - remaining); - // if (count == -1) { - // if (remaining >= required) break; - // throw new KryoException("Buffer underflow."); - // } - // remaining += count; - // if (remaining >= required) break; // Enough has been read. - // } - // limit = remaining; - // byteBuffer.position(0); - return remaining; - } - - /** Fills the buffer with at least the number of bytes specified, if possible. - * @param optional Must be > 0. - * @return the number of bytes remaining, but not more than optional, or -1 if {@link #fill(ByteBuf, int, int)} is unable to - * provide more bytes. */ - protected int optional (int optional) throws KryoException { - int remaining = limit - position; - if (remaining >= optional) return optional; - optional = Math.min(optional, capacity); - - // Try to fill the buffer. - int count = fill(byteBuf, limit, capacity - limit); - if (count == -1) return remaining == 0 ? -1 : Math.min(remaining, optional); - remaining += count; - if (remaining >= optional) { - limit += count; - return optional; - } - - // Compact. - // CANNOT COMPACT A BYTEBUF - // byteBuffer.compact(); - // total += position; - // position = 0; - // - // while (true) { - // count = fill(byteBuffer, remaining, capacity - remaining); - // if (count == -1) break; - // remaining += count; - // if (remaining >= optional) break; // Enough has been read. - // } - // limit = remaining; - // byteBuffer.position(position); - return remaining == 0 ? -1 : Math.min(remaining, optional); - } - - // InputStream: - - public int read () throws KryoException { - if (optional(1) <= 0) return -1; - position++; - return byteBuf.readByte() & 0xFF; - } - - public int read (byte[] bytes) throws KryoException { - return read(bytes, 0, bytes.length); - } - - public int read (byte[] bytes, int offset, int count) throws KryoException { - if (bytes == null) throw new IllegalArgumentException("bytes cannot be null."); - int startingCount = count; - int copyCount = Math.min(limit - position, count); - while (true) { - byteBuf.getBytes(offset, bytes, 0, copyCount); - position += copyCount; - count -= copyCount; - if (count == 0) break; - offset += copyCount; - copyCount = optional(count); - if (copyCount == -1) { - // End of data. - if (startingCount == count) return -1; - break; - } - if (position == limit) break; - } - return startingCount - count; - } - - public void setPosition (int position) { - this.position = position; - byteBuf.readerIndex(position); - } - - public void setLimit (int limit) { - this.limit = limit; - byteBuf.writerIndex(limit); - } - - public void skip (int count) throws KryoException { - super.skip(count); - byteBuf.readerIndex(position); - } - - public long skip (long count) throws KryoException { - long remaining = count; - while (remaining > 0) { - int skip = (int)Math.min(Util.maxArraySize, remaining); - skip(skip); - remaining -= skip; - } - return count; - } - - public void close () throws KryoException { - if (inputStream != null) { - try { - inputStream.close(); - } catch (IOException ignored) { - } - } - } - - // byte: - - public byte readByte () throws KryoException { - if (position == limit) require(1); - position++; - return byteBuf.readByte(); - } - - public int readByteUnsigned () throws KryoException { - if (position == limit) require(1); - position++; - return byteBuf.readByte() & 0xFF; - } - - public byte[] readBytes (int length) throws KryoException { - byte[] bytes = new byte[length]; - readBytes(bytes, 0, length); - return bytes; - } - - public void readBytes (byte[] bytes, int offset, int count) throws KryoException { - if (bytes == null) throw new IllegalArgumentException("bytes cannot be null."); - int copyCount = Math.min(limit - position, count); - while (true) { - byteBuf.readBytes(bytes, offset, copyCount); - position += copyCount; - count -= copyCount; - if (count == 0) break; - offset += copyCount; - copyCount = Math.min(count, capacity); - require(copyCount); - } - } - - // int: - - public int readInt () throws KryoException { - require(4); - position += 4; - ByteBuf byteBuf = this.byteBuf; - return byteBuf.readByte() & 0xFF // - | (byteBuf.readByte() & 0xFF) << 8 // - | (byteBuf.readByte() & 0xFF) << 16 // - | (byteBuf.readByte() & 0xFF) << 24; - } - - public int readVarInt (boolean optimizePositive) throws KryoException { - if (require(1) < 5) return readVarInt_slow(optimizePositive); - int b = byteBuf.readByte(); - int result = b & 0x7F; - if ((b & 0x80) != 0) { - ByteBuf byteBuf = this.byteBuf; - b = byteBuf.readByte(); - result |= (b & 0x7F) << 7; - if ((b & 0x80) != 0) { - b = byteBuf.readByte(); - result |= (b & 0x7F) << 14; - if ((b & 0x80) != 0) { - b = byteBuf.readByte(); - result |= (b & 0x7F) << 21; - if ((b & 0x80) != 0) { - b = byteBuf.readByte(); - result |= (b & 0x7F) << 28; - } - } - } - } - position = byteBuf.readerIndex(); - return optimizePositive ? result : ((result >>> 1) ^ -(result & 1)); - } - - private int readVarInt_slow (boolean optimizePositive) { - // The buffer is guaranteed to have at least 1 byte. - position++; - int b = byteBuf.readByte(); - int result = b & 0x7F; - if ((b & 0x80) != 0) { - if (position == limit) require(1); - ByteBuf byteBuf = this.byteBuf; - position++; - b = byteBuf.readByte(); - result |= (b & 0x7F) << 7; - if ((b & 0x80) != 0) { - if (position == limit) require(1); - position++; - b = byteBuf.readByte(); - result |= (b & 0x7F) << 14; - if ((b & 0x80) != 0) { - if (position == limit) require(1); - position++; - b = byteBuf.readByte(); - result |= (b & 0x7F) << 21; - if ((b & 0x80) != 0) { - if (position == limit) require(1); - position++; - b = byteBuf.readByte(); - result |= (b & 0x7F) << 28; - } - } - } - } - return optimizePositive ? result : ((result >>> 1) ^ -(result & 1)); - } - - public boolean canReadVarInt () throws KryoException { - if (limit - position >= 5) return true; - if (optional(5) <= 0) return false; - int p = position, limit = this.limit; - ByteBuf byteBuf = this.byteBuf; - if ((byteBuf.getByte(p++) & 0x80) == 0) return true; - if (p == limit) return false; - if ((byteBuf.getByte(p++) & 0x80) == 0) return true; - if (p == limit) return false; - if ((byteBuf.getByte(p++) & 0x80) == 0) return true; - if (p == limit) return false; - if ((byteBuf.getByte(p++) & 0x80) == 0) return true; - if (p == limit) return false; - return true; - } - - /** Reads the boolean part of a varint flag. The position is not advanced, {@link #readVarIntFlag(boolean)} should be used to - * advance the position. */ - public boolean readVarIntFlag () { - if (position == limit) require(1); - return (byteBuf.getByte(position) & 0x80) != 0; - } - - /** Reads the 1-5 byte int part of a varint flag. The position is advanced so if the boolean part is needed it should be read - * first with {@link #readVarIntFlag()}. */ - public int readVarIntFlag (boolean optimizePositive) { - if (require(1) < 5) return readVarIntFlag_slow(optimizePositive); - int b = byteBuf.readByte(); - int result = b & 0x3F; // Mask first 6 bits. - if ((b & 0x40) != 0) { // Bit 7 means another byte, bit 8 means UTF8. - ByteBuf byteBuf = this.byteBuf; - b = byteBuf.readByte(); - result |= (b & 0x7F) << 6; - if ((b & 0x80) != 0) { - b = byteBuf.readByte(); - result |= (b & 0x7F) << 13; - if ((b & 0x80) != 0) { - b = byteBuf.readByte(); - result |= (b & 0x7F) << 20; - if ((b & 0x80) != 0) { - b = byteBuf.readByte(); - result |= (b & 0x7F) << 27; - } - } - } - } - position = byteBuf.readerIndex(); - return optimizePositive ? result : ((result >>> 1) ^ -(result & 1)); - } - - private int readVarIntFlag_slow (boolean optimizePositive) { - // The buffer is guaranteed to have at least 1 byte. - position++; - int b = byteBuf.readByte(); - int result = b & 0x3F; - if ((b & 0x40) != 0) { - if (position == limit) require(1); - position++; - ByteBuf byteBuf = this.byteBuf; - b = byteBuf.readByte(); - result |= (b & 0x7F) << 6; - if ((b & 0x80) != 0) { - if (position == limit) require(1); - position++; - b = byteBuf.readByte(); - result |= (b & 0x7F) << 13; - if ((b & 0x80) != 0) { - if (position == limit) require(1); - position++; - b = byteBuf.readByte(); - result |= (b & 0x7F) << 20; - if ((b & 0x80) != 0) { - if (position == limit) require(1); - position++; - b = byteBuf.readByte(); - result |= (b & 0x7F) << 27; - } - } - } - } - return optimizePositive ? result : ((result >>> 1) ^ -(result & 1)); - } - - // long: - - public long readLong () throws KryoException { - require(8); - position += 8; - ByteBuf byteBuf = this.byteBuf; - return byteBuf.readByte() & 0xFF // - | (byteBuf.readByte() & 0xFF) << 8 // - | (byteBuf.readByte() & 0xFF) << 16 // - | (long)(byteBuf.readByte() & 0xFF) << 24 // - | (long)(byteBuf.readByte() & 0xFF) << 32 // - | (long)(byteBuf.readByte() & 0xFF) << 40 // - | (long)(byteBuf.readByte() & 0xFF) << 48 // - | (long)byteBuf.readByte() << 56; - } - - public long readVarLong (boolean optimizePositive) throws KryoException { - if (require(1) < 9) return readVarLong_slow(optimizePositive); - int b = byteBuf.readByte(); - long result = b & 0x7F; - if ((b & 0x80) != 0) { - ByteBuf byteBuf = this.byteBuf; - b = byteBuf.readByte(); - result |= (b & 0x7F) << 7; - if ((b & 0x80) != 0) { - b = byteBuf.readByte(); - result |= (b & 0x7F) << 14; - if ((b & 0x80) != 0) { - b = byteBuf.readByte(); - result |= (b & 0x7F) << 21; - if ((b & 0x80) != 0) { - b = byteBuf.readByte(); - result |= (long)(b & 0x7F) << 28; - if ((b & 0x80) != 0) { - b = byteBuf.readByte(); - result |= (long)(b & 0x7F) << 35; - if ((b & 0x80) != 0) { - b = byteBuf.readByte(); - result |= (long)(b & 0x7F) << 42; - if ((b & 0x80) != 0) { - b = byteBuf.readByte(); - result |= (long)(b & 0x7F) << 49; - if ((b & 0x80) != 0) { - b = byteBuf.readByte(); - result |= (long)b << 56; - } - } - } - } - } - } - } - } - position = byteBuf.readerIndex(); - return optimizePositive ? result : ((result >>> 1) ^ -(result & 1)); - } - - private long readVarLong_slow (boolean optimizePositive) { - // The buffer is guaranteed to have at least 1 byte. - position++; - int b = byteBuf.readByte(); - long result = b & 0x7F; - if ((b & 0x80) != 0) { - if (position == limit) require(1); - ByteBuf byteBuf = this.byteBuf; - position++; - b = byteBuf.readByte(); - result |= (b & 0x7F) << 7; - if ((b & 0x80) != 0) { - if (position == limit) require(1); - position++; - b = byteBuf.readByte(); - result |= (b & 0x7F) << 14; - if ((b & 0x80) != 0) { - if (position == limit) require(1); - position++; - b = byteBuf.readByte(); - result |= (b & 0x7F) << 21; - if ((b & 0x80) != 0) { - if (position == limit) require(1); - position++; - b = byteBuf.readByte(); - result |= (long)(b & 0x7F) << 28; - if ((b & 0x80) != 0) { - if (position == limit) require(1); - position++; - b = byteBuf.readByte(); - result |= (long)(b & 0x7F) << 35; - if ((b & 0x80) != 0) { - if (position == limit) require(1); - position++; - b = byteBuf.readByte(); - result |= (long)(b & 0x7F) << 42; - if ((b & 0x80) != 0) { - if (position == limit) require(1); - position++; - b = byteBuf.readByte(); - result |= (long)(b & 0x7F) << 49; - if ((b & 0x80) != 0) { - if (position == limit) require(1); - position++; - b = byteBuf.readByte(); - result |= (long)b << 56; - } - } - } - } - } - } - } - } - return optimizePositive ? result : ((result >>> 1) ^ -(result & 1)); - } - - public boolean canReadVarLong () throws KryoException { - if (limit - position >= 9) return true; - if (optional(5) <= 0) return false; - int p = position, limit = this.limit; - ByteBuf byteBuf = this.byteBuf; - if ((byteBuf.getByte(p++) & 0x80) == 0) return true; - if (p == limit) return false; - if ((byteBuf.getByte(p++) & 0x80) == 0) return true; - if (p == limit) return false; - if ((byteBuf.getByte(p++) & 0x80) == 0) return true; - if (p == limit) return false; - if ((byteBuf.getByte(p++) & 0x80) == 0) return true; - if (p == limit) return false; - if ((byteBuf.getByte(p++) & 0x80) == 0) return true; - if (p == limit) return false; - if ((byteBuf.getByte(p++) & 0x80) == 0) return true; - if (p == limit) return false; - if ((byteBuf.getByte(p++) & 0x80) == 0) return true; - if (p == limit) return false; - if ((byteBuf.getByte(p++) & 0x80) == 0) return true; - if (p == limit) return false; - return true; - } - - // float: - - public float readFloat () throws KryoException { - require(4); - ByteBuf byteBuf = this.byteBuf; - int p = this.position; - this.position = p + 4; - return Float.intBitsToFloat(byteBuf.readByte() & 0xFF // - | (byteBuf.readByte() & 0xFF) << 8 // - | (byteBuf.readByte() & 0xFF) << 16 // - | (byteBuf.readByte() & 0xFF) << 24); - } - - // double: - - public double readDouble () throws KryoException { - require(8); - ByteBuf byteBuf = this.byteBuf; - int p = position; - position = p + 8; - return Double.longBitsToDouble(byteBuf.readByte() & 0xFF // - | (byteBuf.readByte() & 0xFF) << 8 // - | (byteBuf.readByte() & 0xFF) << 16 // - | (long)(byteBuf.readByte() & 0xFF) << 24 // - | (long)(byteBuf.readByte() & 0xFF) << 32 // - | (long)(byteBuf.readByte() & 0xFF) << 40 // - | (long)(byteBuf.readByte() & 0xFF) << 48 // - | (long)byteBuf.readByte() << 56); - } - - // boolean: - - public boolean readBoolean () throws KryoException { - if (position == limit) require(1); - position++; - return byteBuf.readByte() == 1 ? true : false; - } - - // short: - - public short readShort () throws KryoException { - require(2); - position += 2; - return (short)((byteBuf.readByte() & 0xFF) | ((byteBuf.readByte() & 0xFF) << 8)); - } - - public int readShortUnsigned () throws KryoException { - require(2); - position += 2; - return (byteBuf.readByte() & 0xFF) | ((byteBuf.readByte() & 0xFF) << 8); - } - - // char: - - public char readChar () throws KryoException { - require(2); - position += 2; - return (char)((byteBuf.readByte() & 0xFF) | ((byteBuf.readByte() & 0xFF) << 8)); - } - - // String: - - public String readString () { - if (!readVarIntFlag()) return readAsciiString(); // ASCII. - // Null, empty, or UTF8. - int charCount = readVarIntFlag(true); - switch (charCount) { - case 0: - return null; - case 1: - return ""; - } - charCount--; - readUtf8Chars(charCount); - return new String(chars, 0, charCount); - } - - public StringBuilder readStringBuilder () { - if (!readVarIntFlag()) return new StringBuilder(readAsciiString()); // ASCII. - // Null, empty, or UTF8. - int charCount = readVarIntFlag(true); - switch (charCount) { - case 0: - return null; - case 1: - return new StringBuilder(""); - } - charCount--; - readUtf8Chars(charCount); - StringBuilder builder = new StringBuilder(charCount); - builder.append(chars, 0, charCount); - return builder; - } - - private void readUtf8Chars (int charCount) { - if (chars.length < charCount) chars = new char[charCount]; - char[] chars = this.chars; - // Try to read 7 bit ASCII chars. - ByteBuf byteBuf = this.byteBuf; - int charIndex = 0; - int count = Math.min(require(1), charCount); - while (charIndex < count) { - int b = byteBuf.readByte(); - if (b < 0) break; - chars[charIndex++] = (char)b; - } - position += charIndex; - // If buffer didn't hold all chars or any were not ASCII, use slow path for remainder. - if (charIndex < charCount) { - byteBuf.readerIndex(position); - readUtf8Chars_slow(charCount, charIndex); - } - } - - private void readUtf8Chars_slow (int charCount, int charIndex) { - ByteBuf byteBuf = this.byteBuf; - char[] chars = this.chars; - while (charIndex < charCount) { - if (position == limit) require(1); - position++; - int b = byteBuf.readByte() & 0xFF; - switch (b >> 4) { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - chars[charIndex] = (char)b; - break; - case 12: - case 13: - if (position == limit) require(1); - position++; - chars[charIndex] = (char)((b & 0x1F) << 6 | byteBuf.readByte() & 0x3F); - break; - case 14: - require(2); - position += 2; - int b2 = byteBuf.readByte(); - int b3 = byteBuf.readByte(); - chars[charIndex] = (char)((b & 0x0F) << 12 | (b2 & 0x3F) << 6 | b3 & 0x3F); - break; - } - charIndex++; - } - } - - private String readAsciiString () { - char[] chars = this.chars; - ByteBuf byteBuf = this.byteBuf; - int charCount = 0; - for (int n = Math.min(chars.length, limit - position); charCount < n; charCount++) { - int b = byteBuf.readByte(); - if ((b & 0x80) == 0x80) { - position = byteBuf.readerIndex(); - chars[charCount] = (char)(b & 0x7F); - return new String(chars, 0, charCount + 1); - } - chars[charCount] = (char)b; - } - position = byteBuf.readerIndex(); - return readAscii_slow(charCount); - } - - private String readAscii_slow (int charCount) { - char[] chars = this.chars; - ByteBuf byteBuf = this.byteBuf; - while (true) { - if (position == limit) require(1); - position++; - int b = byteBuf.readByte(); - if (charCount == chars.length) { - char[] newChars = new char[charCount * 2]; - System.arraycopy(chars, 0, newChars, 0, charCount); - chars = newChars; - this.chars = newChars; - } - if ((b & 0x80) == 0x80) { - chars[charCount] = (char)(b & 0x7F); - return new String(chars, 0, charCount + 1); - } - chars[charCount++] = (char)b; - } - } - - // Primitive arrays: - - public int[] readInts (int length) throws KryoException { - int[] array = new int[length]; - if (optional(length << 2) == length << 2) { - ByteBuf byteBuf = this.byteBuf; - for (int i = 0; i < length; i++) { - array[i] = byteBuf.readByte() & 0xFF // - | (byteBuf.readByte() & 0xFF) << 8 // - | (byteBuf.readByte() & 0xFF) << 16 // - | (byteBuf.readByte() & 0xFF) << 24; - } - position = byteBuf.readerIndex(); - } else { - for (int i = 0; i < length; i++) - array[i] = readInt(); - } - return array; - } - - public long[] readLongs (int length) throws KryoException { - long[] array = new long[length]; - if (optional(length << 3) == length << 3) { - ByteBuf byteBuf = this.byteBuf; - for (int i = 0; i < length; i++) { - array[i] = byteBuf.readByte() & 0xFF// - | (byteBuf.readByte() & 0xFF) << 8 // - | (byteBuf.readByte() & 0xFF) << 16 // - | (long)(byteBuf.readByte() & 0xFF) << 24 // - | (long)(byteBuf.readByte() & 0xFF) << 32 // - | (long)(byteBuf.readByte() & 0xFF) << 40 // - | (long)(byteBuf.readByte() & 0xFF) << 48 // - | (long)byteBuf.readByte() << 56; - } - position = byteBuf.readerIndex(); - } else { - for (int i = 0; i < length; i++) - array[i] = readLong(); - } - return array; - } - - public float[] readFloats (int length) throws KryoException { - float[] array = new float[length]; - if (optional(length << 2) == length << 2) { - ByteBuf byteBuf = this.byteBuf; - for (int i = 0; i < length; i++) { - array[i] = Float.intBitsToFloat(byteBuf.readByte() & 0xFF // - | (byteBuf.readByte() & 0xFF) << 8 // - | (byteBuf.readByte() & 0xFF) << 16 // - | (byteBuf.readByte() & 0xFF) << 24); - } - position = byteBuf.readerIndex(); - } else { - for (int i = 0; i < length; i++) - array[i] = readFloat(); - } - return array; - } - - public double[] readDoubles (int length) throws KryoException { - double[] array = new double[length]; - if (optional(length << 3) == length << 3) { - ByteBuf byteBuf = this.byteBuf; - for (int i = 0; i < length; i++) { - array[i] = Double.longBitsToDouble(byteBuf.readByte() & 0xFF // - | (byteBuf.readByte() & 0xFF) << 8 // - | (byteBuf.readByte() & 0xFF) << 16 // - | (long)(byteBuf.readByte() & 0xFF) << 24 // - | (long)(byteBuf.readByte() & 0xFF) << 32 // - | (long)(byteBuf.readByte() & 0xFF) << 40 // - | (long)(byteBuf.readByte() & 0xFF) << 48 // - | (long)byteBuf.readByte() << 56); - } - position = byteBuf.readerIndex(); - } else { - for (int i = 0; i < length; i++) - array[i] = readDouble(); - } - return array; - } - - public short[] readShorts (int length) throws KryoException { - short[] array = new short[length]; - if (optional(length << 1) == length << 1) { - ByteBuf byteBuf = this.byteBuf; - for (int i = 0; i < length; i++) - array[i] = (short)((byteBuf.readByte() & 0xFF) | ((byteBuf.readByte() & 0xFF) << 8)); - position = byteBuf.readerIndex(); - } else { - for (int i = 0; i < length; i++) - array[i] = readShort(); - } - return array; - } - - public char[] readChars (int length) throws KryoException { - char[] array = new char[length]; - if (optional(length << 1) == length << 1) { - ByteBuf byteBuf = this.byteBuf; - for (int i = 0; i < length; i++) - array[i] = (char)((byteBuf.readByte() & 0xFF) | ((byteBuf.readByte() & 0xFF) << 8)); - position = byteBuf.readerIndex(); - } else { - for (int i = 0; i < length; i++) - array[i] = readChar(); - } - return array; - } - - public boolean[] readBooleans (int length) throws KryoException { - boolean[] array = new boolean[length]; - if (optional(length) == length) { - ByteBuf byteBuf = this.byteBuf; - for (int i = 0; i < length; i++) - array[i] = byteBuf.readByte() != 0; - position = byteBuf.readerIndex(); - } else { - for (int i = 0; i < length; i++) - array[i] = readBoolean(); - } - return array; - } -} diff --git a/src/dorkbox/network/pipeline/ByteBufOutput.java b/src/dorkbox/network/pipeline/ByteBufOutput.java deleted file mode 100644 index 4696176c..00000000 --- a/src/dorkbox/network/pipeline/ByteBufOutput.java +++ /dev/null @@ -1,826 +0,0 @@ -/* - * Copyright 2010 dorkbox, llc - * - * Licensed 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. - * - * Copyright (c) 2008, Nathan Sweet - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided with the distribution. - * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package dorkbox.network.pipeline; - -import java.io.DataOutput; -import java.io.IOException; -import java.io.OutputStream; - -import com.esotericsoftware.kryo.KryoException; -import com.esotericsoftware.kryo.io.Output; -import com.esotericsoftware.kryo.util.Util; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; - -/** - * An {@link OutputStream} which writes data to a {@link ByteBuf}. - *

- * 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. - *

- * 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. - * - *

- * Utility methods are provided for efficiently reading primitive types and strings. - * - * Modified from KRYO to use ByteBuf. - */ -public class ByteBufOutput extends Output { - - // NOTE: capacity IS NOT USED! - - private ByteBuf byteBuf; - private int initialReaderIndex = 0; - private int initialWriterIndex = 0; - - - /** Creates an uninitialized Output, {@link #setBuffer(ByteBuf)} must be called before the Output is used. */ - public ByteBufOutput () { - } - - /** Creates a new Output for writing to a direct {@link ByteBuf}. - * @param bufferSize The size of the buffer. An exception is thrown if more bytes than this are written and {@link #flush()} - * does not empty the buffer. */ - public ByteBufOutput (int bufferSize) { - this(bufferSize, bufferSize); - } - - /** Creates a new Output for writing to a direct ByteBuffer. - * @param bufferSize The initial size of the buffer. - * @param maxBufferSize If {@link #flush()} does not empty the buffer, the buffer is doubled as needed until it exceeds - * maxBufferSize and an exception is thrown. Can be -1 for no maximum. */ - public ByteBufOutput (int bufferSize, int maxBufferSize) { - if (maxBufferSize < -1) throw new IllegalArgumentException("maxBufferSize cannot be < -1: " + maxBufferSize); - this.maxCapacity = maxBufferSize == -1 ? Util.maxArraySize : maxBufferSize; - byteBuf = Unpooled.buffer(bufferSize); - } - - /** Creates a new Output for writing to a ByteBuffer. */ - public ByteBufOutput (ByteBuf buffer) { - setBuffer(buffer); - } - - /** Creates a new Output for writing to a ByteBuffer. - * @param maxBufferSize If {@link #flush()} does not empty the buffer, the buffer is doubled as needed until it exceeds - * maxBufferSize and an exception is thrown. Can be -1 for no maximum. */ - public ByteBufOutput (ByteBuf buffer, int maxBufferSize) { - setBuffer(buffer, maxBufferSize); - } - - /** @see Output#Output(OutputStream) */ - public ByteBufOutput (OutputStream outputStream) { - this(4096, 4096); - if (outputStream == null) throw new IllegalArgumentException("outputStream cannot be null."); - this.outputStream = outputStream; - } - - /** @see Output#Output(OutputStream, int) */ - public ByteBufOutput (OutputStream outputStream, int bufferSize) { - this(bufferSize, bufferSize); - if (outputStream == null) throw new IllegalArgumentException("outputStream cannot be null."); - this.outputStream = outputStream; - } - - @Override - public OutputStream getOutputStream () { - return outputStream; - } - - /** Throws {@link UnsupportedOperationException} because this output uses a ByteBuffer, not a byte[]. - * @deprecated - * @see #getByteBuf() */ - @Override - @Deprecated - public byte[] getBuffer () { - throw new UnsupportedOperationException("This buffer does not used a byte[], see #getByteBuffer()."); - } - - /** Throws {@link UnsupportedOperationException} because this output uses a ByteBuffer, not a byte[]. - * @deprecated - * @see #getByteBuf() */ - @Override - @Deprecated - public void setBuffer (byte[] buffer) { - throw new UnsupportedOperationException("This buffer does not used a byte[], see #setByteBuffer(ByteBuffer)."); - } - - /** Throws {@link UnsupportedOperationException} because this output uses a ByteBuffer, not a byte[]. - * @deprecated - * @see #getByteBuf() */ - @Override - @Deprecated - public void setBuffer (byte[] buffer, int maxBufferSize) { - throw new UnsupportedOperationException("This buffer does not used a byte[], see #setByteBuffer(ByteBuffer)."); - } - - /** Allocates a new direct ByteBuffer with the specified bytes and sets it as the new buffer. - * @see #setBuffer(ByteBuf) */ - public void setBuffer (byte[] bytes, int offset, int count) { - setBuffer(Unpooled.wrappedBuffer(bytes, offset, count)); - } - - /** Sets a new buffer to write to. The max size is the buffer's length. - * @see #setBuffer(ByteBuf, int) */ - public void setBuffer (ByteBuf buffer) { - setBuffer(buffer, buffer.capacity()); - } - - /** Sets a new buffer to write to. The bytes are not copied, the old buffer is discarded and the new buffer used in its place. - * The position and capacity are set to match the specified buffer. The total is reset. The - * {@link #setOutputStream(OutputStream) OutputStream} is set to null. - * @param maxBufferSize If {@link #flush()} does not empty the buffer, the buffer is doubled as needed until it exceeds - * maxBufferSize and an exception is thrown. Can be -1 for no maximum. */ - public void setBuffer (ByteBuf buffer, int maxBufferSize) { - if (buffer == null) throw new IllegalArgumentException("buffer cannot be null."); - if (maxBufferSize < -1) throw new IllegalArgumentException("maxBufferSize cannot be < -1: " + maxBufferSize); - - initialReaderIndex = buffer.readerIndex(); - initialWriterIndex = buffer.writerIndex(); - - this.byteBuf = buffer; - this.maxCapacity = maxBufferSize == -1 ? Util.maxArraySize : maxBufferSize; - position = initialWriterIndex; - total = 0; - outputStream = null; - } - - /** Returns the buffer. The bytes between zero and {@link #position()} are the data that has been written. */ - public ByteBuf getByteBuf () { - return byteBuf; - } - - @Override - public byte[] toBytes () { - byte[] newBuffer = new byte[position]; - byteBuf.readerIndex(initialReaderIndex); - byteBuf.getBytes(initialReaderIndex, newBuffer, 0, position); - return newBuffer; - } - - @Override - public void setPosition (int position) { - this.position = position; - this.byteBuf.writerIndex(position); - } - - @Override - public void reset () { - super.reset(); - byteBuf.setIndex(initialReaderIndex, initialWriterIndex); - } - - /** - * Ensures the buffer is large enough to read the specified number of bytes. - * @return true if the buffer has been resized. - */ - @Override - protected boolean require (int required) throws KryoException { - if (byteBuf.isWritable(required)) { - return false; - } - - int origCode = byteBuf.ensureWritable(required, true); - - if (origCode == 0) { - // 0 if the buffer has enough writable bytes, and its capacity is unchanged. - return false; - } - else if (origCode == 2) { - // 2 if the buffer has enough writable bytes, and its capacity has been increased. - return true; - } - else if (origCode == 3) { - // 3 if the buffer does not have enough bytes, but its capacity has been increased to its maximum. - return true; - } - else { - // flush and try again. - flush(); - } - - // only got here because we were unable to resize the buffer! So we flushed it first to try again! - origCode = byteBuf.ensureWritable(required, true); - - if (origCode == 0) { - // 0 if the buffer has enough writable bytes, and its capacity is unchanged. - return false; - } else if (origCode == 1) { - // 1 if the buffer does not have enough bytes, and its capacity is unchanged. - throw new KryoException("Buffer overflow. Max capacity: " + maxCapacity + ", required: " + required); - } - else if (origCode == 2) { - // 2 if the buffer has enough writable bytes, and its capacity has been increased. - return true; - } - else if (origCode == 3) { - // 3 if the buffer does not have enough bytes, but its capacity has been increased to its maximum. - return true; - } - else { - throw new KryoException("Unknown buffer resize code: " + origCode); - } - } - - // OutputStream: - - @Override - public void flush () throws KryoException { - if (outputStream == null) return; - try { - byte[] tmp = new byte[position]; - byteBuf.getBytes(initialReaderIndex, tmp); - byteBuf.readerIndex(initialReaderIndex); - outputStream.write(tmp, 0, position); - } catch (IOException ex) { - throw new KryoException(ex); - } - total += position; - position = 0; - } - - @Override - public void close () throws KryoException { - flush(); - if (outputStream != null) { - try { - outputStream.close(); - } catch (IOException ignored) { - } - } - } - - @Override - public void write (int value) throws KryoException { - require(1); - byteBuf.writeByte((byte)value); - position++; - } - - @Override - public void write (byte[] bytes) throws KryoException { - if (bytes == null) throw new IllegalArgumentException("bytes cannot be null."); - writeBytes(bytes, 0, bytes.length); - } - - @Override - public void write (byte[] bytes, int offset, int length) throws KryoException { - writeBytes(bytes, offset, length); - } - - // byte: - - @Override - public void writeByte (byte value) throws KryoException { - require(1); - byteBuf.writeByte(value); - position++; - } - - @Override - public void writeByte (int value) throws KryoException { - require(1); - byteBuf.writeByte((byte)value); - position++; - } - - @Override - public void writeBytes (byte[] bytes) throws KryoException { - if (bytes == null) throw new IllegalArgumentException("bytes cannot be null."); - writeBytes(bytes, 0, bytes.length); - } - - @Override - public void writeBytes (byte[] bytes, int offset, int count) throws KryoException { - if (bytes == null) throw new IllegalArgumentException("bytes cannot be null."); - - require(count); - byteBuf.writeBytes(bytes, offset, count); - position += count; - } - - // int: - - @Override - public void writeInt (int value) throws KryoException { - require(4); - position += 4; - ByteBuf byteBuf = this.byteBuf; - byteBuf.writeByte((byte)value); - byteBuf.writeByte((byte)(value >> 8)); - byteBuf.writeByte((byte)(value >> 16)); - byteBuf.writeByte((byte)(value >> 24)); - } - - @Override - public int writeVarInt (int value, boolean optimizePositive) throws KryoException { - if (!optimizePositive) value = (value << 1) ^ (value >> 31); - if (value >>> 7 == 0) { - require(1); - position++; - byteBuf.writeByte((byte)value); - return 1; - } - if (value >>> 14 == 0) { - require(2); - position += 2; - byteBuf.writeByte((byte)((value & 0x7F) | 0x80)); - byteBuf.writeByte((byte)(value >>> 7)); - return 2; - } - if (value >>> 21 == 0) { - require(3); - position += 3; - ByteBuf byteBuf = this.byteBuf; - byteBuf.writeByte((byte)((value & 0x7F) | 0x80)); - byteBuf.writeByte((byte)(value >>> 7 | 0x80)); - byteBuf.writeByte((byte)(value >>> 14)); - return 3; - } - if (value >>> 28 == 0) { - require(4); - position += 4; - ByteBuf byteBuf = this.byteBuf; - byteBuf.writeByte((byte)((value & 0x7F) | 0x80)); - byteBuf.writeByte((byte)(value >>> 7 | 0x80)); - byteBuf.writeByte((byte)(value >>> 14 | 0x80)); - byteBuf.writeByte((byte)(value >>> 21)); - return 4; - } - require(5); - position += 5; - ByteBuf byteBuf = this.byteBuf; - byteBuf.writeByte((byte)((value & 0x7F) | 0x80)); - byteBuf.writeByte((byte)(value >>> 7 | 0x80)); - byteBuf.writeByte((byte)(value >>> 14 | 0x80)); - byteBuf.writeByte((byte)(value >>> 21 | 0x80)); - byteBuf.writeByte((byte)(value >>> 28)); - return 5; - } - - @Override - public int writeVarIntFlag (boolean flag, int value, boolean optimizePositive) throws KryoException { - if (!optimizePositive) value = (value << 1) ^ (value >> 31); - int first = (value & 0x3F) | (flag ? 0x80 : 0); // Mask first 6 bits, bit 8 is the flag. - if (value >>> 6 == 0) { - require(1); - byteBuf.writeByte((byte)first); - position++; - return 1; - } - if (value >>> 13 == 0) { - require(2); - position += 2; - byteBuf.writeByte((byte)(first | 0x40)); // Set bit 7. - byteBuf.writeByte((byte)(value >>> 6)); - return 2; - } - if (value >>> 20 == 0) { - require(3); - position += 3; - ByteBuf byteBuf = this.byteBuf; - byteBuf.writeByte((byte)(first | 0x40)); // Set bit 7. - byteBuf.writeByte((byte)((value >>> 6) | 0x80)); // Set bit 8. - byteBuf.writeByte((byte)(value >>> 13)); - return 3; - } - if (value >>> 27 == 0) { - require(4); - position += 4; - ByteBuf byteBuf = this.byteBuf; - byteBuf.writeByte((byte)(first | 0x40)); // Set bit 7. - byteBuf.writeByte((byte)((value >>> 6) | 0x80)); // Set bit 8. - byteBuf.writeByte((byte)((value >>> 13) | 0x80)); // Set bit 8. - byteBuf.writeByte((byte)(value >>> 20)); - return 4; - } - require(5); - position += 5; - ByteBuf byteBuf = this.byteBuf; - byteBuf.writeByte((byte)(first | 0x40)); // Set bit 7. - byteBuf.writeByte((byte)((value >>> 6) | 0x80)); // Set bit 8. - byteBuf.writeByte((byte)((value >>> 13) | 0x80)); // Set bit 8. - byteBuf.writeByte((byte)((value >>> 20) | 0x80)); // Set bit 8. - byteBuf.writeByte((byte)(value >>> 27)); - return 5; - } - - // long: - - @Override - public void writeLong (long value) throws KryoException { - require(8); - position += 8; - ByteBuf byteBuf = this.byteBuf; - byteBuf.writeByte((byte)value); - byteBuf.writeByte((byte)(value >>> 8)); - byteBuf.writeByte((byte)(value >>> 16)); - byteBuf.writeByte((byte)(value >>> 24)); - byteBuf.writeByte((byte)(value >>> 32)); - byteBuf.writeByte((byte)(value >>> 40)); - byteBuf.writeByte((byte)(value >>> 48)); - byteBuf.writeByte((byte)(value >>> 56)); - } - - @Override - public int writeVarLong (long value, boolean optimizePositive) throws KryoException { - if (!optimizePositive) value = (value << 1) ^ (value >> 63); - if (value >>> 7 == 0) { - require(1); - position++; - byteBuf.writeByte((byte)value); - return 1; - } - if (value >>> 14 == 0) { - require(2); - position += 2; - byteBuf.writeByte((byte)((value & 0x7F) | 0x80)); - byteBuf.writeByte((byte)(value >>> 7)); - return 2; - } - if (value >>> 21 == 0) { - require(3); - position += 3; - ByteBuf byteBuf = this.byteBuf; - byteBuf.writeByte((byte)((value & 0x7F) | 0x80)); - byteBuf.writeByte((byte)(value >>> 7 | 0x80)); - byteBuf.writeByte((byte)(value >>> 14)); - return 3; - } - if (value >>> 28 == 0) { - require(4); - position += 4; - ByteBuf byteBuf = this.byteBuf; - byteBuf.writeByte((byte)((value & 0x7F) | 0x80)); - byteBuf.writeByte((byte)(value >>> 7 | 0x80)); - byteBuf.writeByte((byte)(value >>> 14 | 0x80)); - byteBuf.writeByte((byte)(value >>> 21)); - return 4; - } - if (value >>> 35 == 0) { - require(5); - position += 5; - ByteBuf byteBuf = this.byteBuf; - byteBuf.writeByte((byte)((value & 0x7F) | 0x80)); - byteBuf.writeByte((byte)(value >>> 7 | 0x80)); - byteBuf.writeByte((byte)(value >>> 14 | 0x80)); - byteBuf.writeByte((byte)(value >>> 21 | 0x80)); - byteBuf.writeByte((byte)(value >>> 28)); - return 5; - } - if (value >>> 42 == 0) { - require(6); - position += 6; - ByteBuf byteBuf = this.byteBuf; - byteBuf.writeByte((byte)((value & 0x7F) | 0x80)); - byteBuf.writeByte((byte)(value >>> 7 | 0x80)); - byteBuf.writeByte((byte)(value >>> 14 | 0x80)); - byteBuf.writeByte((byte)(value >>> 21 | 0x80)); - byteBuf.writeByte((byte)(value >>> 28 | 0x80)); - byteBuf.writeByte((byte)(value >>> 35)); - return 6; - } - if (value >>> 49 == 0) { - require(7); - position += 7; - ByteBuf byteBuf = this.byteBuf; - byteBuf.writeByte((byte)((value & 0x7F) | 0x80)); - byteBuf.writeByte((byte)(value >>> 7 | 0x80)); - byteBuf.writeByte((byte)(value >>> 14 | 0x80)); - byteBuf.writeByte((byte)(value >>> 21 | 0x80)); - byteBuf.writeByte((byte)(value >>> 28 | 0x80)); - byteBuf.writeByte((byte)(value >>> 35 | 0x80)); - byteBuf.writeByte((byte)(value >>> 42)); - return 7; - } - if (value >>> 56 == 0) { - require(8); - position += 8; - ByteBuf byteBuf = this.byteBuf; - byteBuf.writeByte((byte)((value & 0x7F) | 0x80)); - byteBuf.writeByte((byte)(value >>> 7 | 0x80)); - byteBuf.writeByte((byte)(value >>> 14 | 0x80)); - byteBuf.writeByte((byte)(value >>> 21 | 0x80)); - byteBuf.writeByte((byte)(value >>> 28 | 0x80)); - byteBuf.writeByte((byte)(value >>> 35 | 0x80)); - byteBuf.writeByte((byte)(value >>> 42 | 0x80)); - byteBuf.writeByte((byte)(value >>> 49)); - return 8; - } - require(9); - position += 9; - ByteBuf byteBuf = this.byteBuf; - byteBuf.writeByte((byte)((value & 0x7F) | 0x80)); - byteBuf.writeByte((byte)(value >>> 7 | 0x80)); - byteBuf.writeByte((byte)(value >>> 14 | 0x80)); - byteBuf.writeByte((byte)(value >>> 21 | 0x80)); - byteBuf.writeByte((byte)(value >>> 28 | 0x80)); - byteBuf.writeByte((byte)(value >>> 35 | 0x80)); - byteBuf.writeByte((byte)(value >>> 42 | 0x80)); - byteBuf.writeByte((byte)(value >>> 49 | 0x80)); - byteBuf.writeByte((byte)(value >>> 56)); - return 9; - } - - // float: - - @Override - public void writeFloat (float value) throws KryoException { - require(4); - ByteBuf byteBuf = this.byteBuf; - position += 4; - int intValue = Float.floatToIntBits(value); - byteBuf.writeByte((byte)intValue); - byteBuf.writeByte((byte)(intValue >> 8)); - byteBuf.writeByte((byte)(intValue >> 16)); - byteBuf.writeByte((byte)(intValue >> 24)); - } - - // double: - - @Override - public void writeDouble (double value) throws KryoException { - require(8); - position += 8; - ByteBuf byteBuf = this.byteBuf; - long longValue = Double.doubleToLongBits(value); - byteBuf.writeByte((byte)longValue); - byteBuf.writeByte((byte)(longValue >>> 8)); - byteBuf.writeByte((byte)(longValue >>> 16)); - byteBuf.writeByte((byte)(longValue >>> 24)); - byteBuf.writeByte((byte)(longValue >>> 32)); - byteBuf.writeByte((byte)(longValue >>> 40)); - byteBuf.writeByte((byte)(longValue >>> 48)); - byteBuf.writeByte((byte)(longValue >>> 56)); - } - - // short: - - @Override - public void writeShort (int value) throws KryoException { - require(2); - position += 2; - byteBuf.writeByte((byte)value); - byteBuf.writeByte((byte)(value >>> 8)); - } - - // char: - - @Override - public void writeChar (char value) throws KryoException { - require(2); - position += 2; - byteBuf.writeByte((byte)value); - byteBuf.writeByte((byte)(value >>> 8)); - } - - // boolean: - - @Override - public void writeBoolean (boolean value) throws KryoException { - require(1); - byteBuf.writeByte((byte)(value ? 1 : 0)); - position++; - } - - // String: - - @Override - public void writeString (String value) throws KryoException { - if (value == null) { - writeByte(0x80); // 0 means null, bit 8 means UTF8. - return; - } - int charCount = value.length(); - if (charCount == 0) { - writeByte(1 | 0x80); // 1 means empty string, bit 8 means UTF8. - return; - } - - require(charCount); // must be able to write this number of chars - - // Detect ASCII, we only do this for small strings, but ONLY more than 1 char. - // since 1 char is used for bit-masking if we use for 1 char string, reading the string will not work! - boolean isAscii = charCount > 1 && charCount <= 32; - - if (isAscii) { - for (int i = 0; i < charCount; i++) { - if (value.charAt(i) > 127) { - isAscii = false; - break; // not ascii - } - } - } - - if (isAscii) { - // this is ascii - for (int i = 0, n = value.length(); i < n; ++i) { - byteBuf.writeByte((byte)value.charAt(i)); - } - position += charCount; - - byteBuf.setByte(position - 1, (byte)(byteBuf.getByte(position - 1) | 0x80)); - } else { - writeVarIntFlag(true, charCount + 1, true); - - int charIndex = 0; - // Try to write 7 bit chars. - ByteBuf byteBuf = this.byteBuf; - while (true) { - int c = value.charAt(charIndex); - if (c > 127) break; - byteBuf.writeByte((byte)c); - charIndex++; - if (charIndex == charCount) { - position = byteBuf.writerIndex(); - return; - } - } - position = byteBuf.writerIndex(); - - if (charIndex < charCount) writeUtf8_slow(value, charCount, charIndex); - } - } - - @Override - public void writeAscii (String value) throws KryoException { - if (value == null) { - writeByte(0x80); // 0 means null, bit 8 means UTF8. - return; - } - int charCount = value.length(); - if (charCount == 0) { - writeByte(1 | 0x80); // 1 means empty string, bit 8 means UTF8. - return; - } - - require(charCount); // must be able to write this number of chars - - ByteBuf byteBuf = this.byteBuf; - for (int i = 0, n = value.length(); i < n; ++i) { - byteBuf.writeByte((byte)value.charAt(i)); - } - - position += charCount; - byteBuf.setByte(position - 1, (byte)(byteBuf.getByte(position - 1) | 0x80)); // Bit 8 means end of ASCII. - } - - private void writeUtf8_slow (String value, int charCount, int charIndex) { - for (; charIndex < charCount; charIndex++) { - int c = value.charAt(charIndex); - if (c <= 0x007F) { - writeByte((byte)c); - } - else if (c > 0x07FF) { - require(3); - byteBuf.writeByte((byte)(0xE0 | c >> 12 & 0x0F)); - byteBuf.writeByte((byte)(0x80 | c >> 6 & 0x3F)); - byteBuf.writeByte((byte)(0x80 | c & 0x3F)); - position += 3; - } else { - require(2); - byteBuf.writeByte((byte)(0xC0 | c >> 6 & 0x1F)); - byteBuf.writeByte((byte)(0x80 | c & 0x3F)); - position += 2; - } - } - } - - // Primitive arrays: - - @Override - public void writeInts (int[] array, int offset, int count) throws KryoException { - require(count << 2); - - ByteBuf byteBuf = this.byteBuf; - for (int n = offset + count; offset < n; offset++) { - int value = array[offset]; - byteBuf.writeByte((byte)value); - byteBuf.writeByte((byte)(value >> 8)); - byteBuf.writeByte((byte)(value >> 16)); - byteBuf.writeByte((byte)(value >> 24)); - } - position = byteBuf.writerIndex(); - } - - @Override - public void writeLongs (long[] array, int offset, int count) throws KryoException { - require(count << 3); - - ByteBuf byteBuf = this.byteBuf; - for (int n = offset + count; offset < n; offset++) { - long value = array[offset]; - byteBuf.writeByte((byte)value); - byteBuf.writeByte((byte)(value >>> 8)); - byteBuf.writeByte((byte)(value >>> 16)); - byteBuf.writeByte((byte)(value >>> 24)); - byteBuf.writeByte((byte)(value >>> 32)); - byteBuf.writeByte((byte)(value >>> 40)); - byteBuf.writeByte((byte)(value >>> 48)); - byteBuf.writeByte((byte)(value >>> 56)); - } - position = byteBuf.writerIndex(); - } - - @Override - public void writeFloats (float[] array, int offset, int count) throws KryoException { - require(count << 2); - - ByteBuf byteBuf = this.byteBuf; - for (int n = offset + count; offset < n; offset++) { - int value = Float.floatToIntBits(array[offset]); - byteBuf.writeByte((byte)value); - byteBuf.writeByte((byte)(value >> 8)); - byteBuf.writeByte((byte)(value >> 16)); - byteBuf.writeByte((byte)(value >> 24)); - } - position = byteBuf.writerIndex(); - } - - @Override - public void writeDoubles (double[] array, int offset, int count) throws KryoException { - require(count << 3); - - ByteBuf byteBuf = this.byteBuf; - for (int n = offset + count; offset < n; offset++) { - long value = Double.doubleToLongBits(array[offset]); - byteBuf.writeByte((byte)value); - byteBuf.writeByte((byte)(value >>> 8)); - byteBuf.writeByte((byte)(value >>> 16)); - byteBuf.writeByte((byte)(value >>> 24)); - byteBuf.writeByte((byte)(value >>> 32)); - byteBuf.writeByte((byte)(value >>> 40)); - byteBuf.writeByte((byte)(value >>> 48)); - byteBuf.writeByte((byte)(value >>> 56)); - } - position = byteBuf.writerIndex(); - } - - @Override - public void writeShorts (short[] array, int offset, int count) throws KryoException { - require(count << 1); - - for (int n = offset + count; offset < n; offset++) { - int value = array[offset]; - byteBuf.writeByte((byte)value); - byteBuf.writeByte((byte)(value >>> 8)); - } - position = byteBuf.writerIndex(); - } - - @Override - public void writeChars (char[] array, int offset, int count) throws KryoException { - require(count << 1); - - for (int n = offset + count; offset < n; offset++) { - int value = array[offset]; - byteBuf.writeByte((byte)value); - byteBuf.writeByte((byte)(value >>> 8)); - } - position = byteBuf.writerIndex(); - } - - @Override - public void writeBooleans (boolean[] array, int offset, int count) throws KryoException { - require(count); - - for (int n = offset + count; offset < n; offset++) - byteBuf.writeByte(array[offset] ? (byte)1 : 0); - position = byteBuf.writerIndex(); - } -}