com.esotericsoftware.kryo.io.ByteBufferInput Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kryo-slf4j-shaded Show documentation
Show all versions of kryo-slf4j-shaded Show documentation
Fork of Esoteric Software's Kryo built by Nathan Sweet that replaces Minlog with slf4j as the logging facade. This contains the shaded reflectasm jar to prevent conflicts with other versions of asm.
The newest version!
/* 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 com.esotericsoftware.kryo.io;
import com.esotericsoftware.kryo.KryoException;
import com.esotericsoftware.kryo.util.UnsafeUtil;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.CharBuffer;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.LongBuffer;
import java.nio.ShortBuffer;
/** An InputStream that reads data from a byte array and optionally fills the byte array from another InputStream as needed.
* Utility methods are provided for efficiently reading primitive types and strings.
*
* @author Roman Levenstein */
public class ByteBufferInput extends Input {
protected ByteBuffer niobuffer;
protected boolean varIntsEnabled = true;
/* Default byte order is BIG_ENDIAN to be compatible to the base class */
ByteOrder byteOrder = ByteOrder.BIG_ENDIAN;
protected final static ByteOrder nativeOrder = ByteOrder.nativeOrder();
/** Creates an uninitialized Input. A buffer must be set before the Input is used.
* @see #setBuffer(ByteBuffer) */
public ByteBufferInput () {
}
/** Creates a new Input for reading from a byte array.
* @param bufferSize The size of the buffer. An exception is thrown if more bytes than this are read. */
public ByteBufferInput (int bufferSize) {
this.capacity = bufferSize;
niobuffer = ByteBuffer.allocateDirect(bufferSize);
niobuffer.order(byteOrder);
}
public ByteBufferInput (byte[] buffer) {
setBuffer(buffer);
}
/** Creates a new Input for reading from a ByteBuffer. */
public ByteBufferInput (ByteBuffer buffer) {
setBuffer(buffer);
}
/** Creates a new Input for reading from an InputStream with a buffer size of 4096. */
public ByteBufferInput (InputStream inputStream) {
this(4096);
if (inputStream == null) throw new IllegalArgumentException("inputStream cannot be null.");
this.inputStream = inputStream;
}
/** Creates a new Input for reading from an InputStream. */
public ByteBufferInput (InputStream inputStream, int bufferSize) {
this(bufferSize);
if (inputStream == null) throw new IllegalArgumentException("inputStream cannot be null.");
this.inputStream = inputStream;
}
public ByteOrder order () {
return byteOrder;
}
public void order (ByteOrder byteOrder) {
this.byteOrder = byteOrder;
}
/** Sets a new buffer, discarding any previous buffer. The position and total are reset. */
public void setBuffer (byte[] bytes) {
ByteBuffer directBuffer = ByteBuffer.allocateDirect(bytes.length);
directBuffer.put(bytes);
directBuffer.position(0);
directBuffer.limit(bytes.length);
directBuffer.order(byteOrder);
setBuffer(directBuffer);
}
/** Sets a new buffer, discarding any previous buffer. The byte order, 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 (ByteBuffer buffer) {
if (buffer == null) throw new IllegalArgumentException("buffer cannot be null.");
niobuffer = buffer;
position = buffer.position();
limit = buffer.limit();
capacity = buffer.capacity();
total = 0;
inputStream = null;
}
/** Releases a direct buffer. {@link #setBuffer(ByteBuffer)} must be called before any write operations can be performed. */
public void release () {
close();
UnsafeUtil.releaseBuffer(niobuffer);
niobuffer = null;
}
/** This constructor allows for creation of a direct ByteBuffer of a given size at a given address.
*
*
* Typical usage could look like this snippet:
*
*
* // Explicitly allocate memory
* long bufAddress = UnsafeUtil.unsafe().allocateMemory(4096);
* // Create a ByteBufferInput using the allocated memory region
* ByteBufferInput buffer = new ByteBufferInput(bufAddress, 4096);
*
* // Do some operations on this buffer here
*
* // Say that ByteBuffer won't be used anymore
* buffer.release();
* // Release the allocated region
* UnsafeUtil.unsafe().freeMemory(bufAddress);
*
*
* @param address starting address of a memory region pre-allocated using Unsafe.allocateMemory() */
public ByteBufferInput (long address, int size) {
setBuffer(UnsafeUtil.getDirectBufferAt(address, size));
}
public ByteBuffer getByteBuffer () {
return niobuffer;
}
public InputStream getInputStream () {
return inputStream;
}
/** Sets a new InputStream. The position and total are reset, discarding any buffered bytes.
* @param inputStream May be null. */
public void setInputStream (InputStream inputStream) {
this.inputStream = inputStream;
limit = 0;
rewind();
}
public void rewind () {
super.rewind();
niobuffer.position(0);
}
/** Fills the buffer with more bytes. Can be overridden to fill the bytes from a source other than the InputStream. */
protected int fill (ByteBuffer buffer, int offset, int count) throws KryoException {
if (inputStream == null) return -1;
try {
byte[] tmp = new byte[count];
int result = inputStream.read(tmp, 0, count);
buffer.position(offset);
if (result >= 0) {
buffer.put(tmp, 0, result);
buffer.position(offset);
}
return result;
} catch (IOException ex) {
throw new KryoException(ex);
}
}
/** @param required Must be > 0. The buffer is filled until it has at least this many bytes.
* @return the number of bytes remaining.
* @throws KryoException if EOS is reached before required bytes are read (buffer underflow). */
final 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(niobuffer, 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
niobuffer.position(position);
niobuffer.compact();
total += position;
position = 0;
while (true) {
count = fill(niobuffer, 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;
niobuffer.position(0);
return remaining;
}
/** @param optional Try to fill the buffer with this many bytes.
* @return the number of bytes remaining, but not more than optional, or -1 if the EOS was reached and the buffer is empty. */
private 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(niobuffer, limit, capacity - limit);
if (count == -1) return remaining == 0 ? -1 : Math.min(remaining, optional);
remaining += count;
if (remaining >= optional) {
limit += count;
return optional;
}
// Compact.
niobuffer.compact();
total += position;
position = 0;
while (true) {
count = fill(niobuffer, remaining, capacity - remaining);
if (count == -1) break;
remaining += count;
if (remaining >= optional) break; // Enough has been read.
}
limit = remaining;
niobuffer.position(position);
return remaining == 0 ? -1 : Math.min(remaining, optional);
}
// InputStream
/** Reads a single byte as an int from 0 to 255, or -1 if there are no more bytes are available. */
public int read () throws KryoException {
if (optional(1) <= 0) return -1;
niobuffer.position(position);
position++;
return niobuffer.get() & 0xFF;
}
/** Reads bytes.length bytes or less and writes them to the specified byte[], starting at 0, and returns the number of bytes
* read. */
public int read (byte[] bytes) throws KryoException {
niobuffer.position(position);
return read(bytes, 0, bytes.length);
}
/** Reads count bytes or less and writes them to the specified byte[], starting at offset, and returns the number of bytes read
* or -1 if no more bytes are available. */
public int read (byte[] bytes, int offset, int count) throws KryoException {
niobuffer.position(position);
if (bytes == null) throw new IllegalArgumentException("bytes cannot be null.");
int startingCount = count;
int copyCount = Math.min(limit - position, count);
while (true) {
niobuffer.get(bytes, offset, 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;
}
/** Discards the specified number of bytes. */
public long skip (long count) throws KryoException {
long remaining = count;
while (remaining > 0) {
int skip = (int)Math.min(Integer.MAX_VALUE, remaining);
skip(skip);
remaining -= skip;
}
return count;
}
/** Closes the underlying InputStream, if any. */
public void close () throws KryoException {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException ignored) {
}
}
}
// byte
/** Reads a single byte. */
public byte readByte () throws KryoException {
niobuffer.position(position);
require(1);
position++;
return niobuffer.get();
}
/** Reads a byte as an int from 0 to 255. */
public int readByteUnsigned () throws KryoException {
// buffer.position(position);
require(1);
position++;
return niobuffer.get() & 0xFF;
}
/** Reads the specified number of bytes into a new byte[]. */
public byte[] readBytes (int length) throws KryoException {
byte[] bytes = new byte[length];
readBytes(bytes, 0, length);
return bytes;
}
/** Reads bytes.length bytes and writes them to the specified byte[], starting at index 0. */
public void readBytes (byte[] bytes) throws KryoException {
readBytes(bytes, 0, bytes.length);
}
/** Reads count bytes and writes them to the specified byte[], starting at offset. */
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) {
niobuffer.get(bytes, offset, copyCount);
position += copyCount;
count -= copyCount;
if (count == 0) break;
offset += copyCount;
copyCount = Math.min(count, capacity);
require(copyCount);
}
}
public int readInt () throws KryoException {
require(4);
position += 4;
return niobuffer.getInt();
}
public int readInt (boolean optimizePositive) throws KryoException {
if (varIntsEnabled)
return readVarInt(optimizePositive);
else
return readInt();
}
public int readVarInt (boolean optimizePositive) throws KryoException {
niobuffer.position(position);
if (require(1) < 5) return readInt_slow(optimizePositive);
position++;
int b = niobuffer.get();
int result = b & 0x7F;
if ((b & 0x80) != 0) {
position++;
b = niobuffer.get();
result |= (b & 0x7F) << 7;
if ((b & 0x80) != 0) {
position++;
b = niobuffer.get();
result |= (b & 0x7F) << 14;
if ((b & 0x80) != 0) {
position++;
b = niobuffer.get();
result |= (b & 0x7F) << 21;
if ((b & 0x80) != 0) {
position++;
b = niobuffer.get();
result |= (b & 0x7F) << 28;
}
}
}
}
return optimizePositive ? result : ((result >>> 1) ^ -(result & 1));
}
private int readInt_slow (boolean optimizePositive) {
// The buffer is guaranteed to have at least 1 byte.
position++;
int b = niobuffer.get();
int result = b & 0x7F;
if ((b & 0x80) != 0) {
require(1);
position++;
b = niobuffer.get();
result |= (b & 0x7F) << 7;
if ((b & 0x80) != 0) {
require(1);
position++;
b = niobuffer.get();
result |= (b & 0x7F) << 14;
if ((b & 0x80) != 0) {
require(1);
position++;
b = niobuffer.get();
result |= (b & 0x7F) << 21;
if ((b & 0x80) != 0) {
require(1);
position++;
b = niobuffer.get();
result |= (b & 0x7F) << 28;
}
}
}
}
return optimizePositive ? result : ((result >>> 1) ^ -(result & 1));
}
/** Returns true if enough bytes are available to read an int with {@link #readInt(boolean)}. */
public boolean canReadInt () throws KryoException {
if (limit - position >= 5) return true;
if (optional(5) <= 0) return false;
int p = position;
if ((niobuffer.get(p++) & 0x80) == 0) return true;
if (p == limit) return false;
if ((niobuffer.get(p++) & 0x80) == 0) return true;
if (p == limit) return false;
if ((niobuffer.get(p++) & 0x80) == 0) return true;
if (p == limit) return false;
if ((niobuffer.get(p++) & 0x80) == 0) return true;
if (p == limit) return false;
return true;
}
/** Returns true if enough bytes are available to read a long with {@link #readLong(boolean)}. */
public boolean canReadLong () throws KryoException {
if (limit - position >= 9) return true;
if (optional(5) <= 0) return false;
int p = position;
if ((niobuffer.get(p++) & 0x80) == 0) return true;
if (p == limit) return false;
if ((niobuffer.get(p++) & 0x80) == 0) return true;
if (p == limit) return false;
if ((niobuffer.get(p++) & 0x80) == 0) return true;
if (p == limit) return false;
if ((niobuffer.get(p++) & 0x80) == 0) return true;
if (p == limit) return false;
if ((niobuffer.get(p++) & 0x80) == 0) return true;
if (p == limit) return false;
if ((niobuffer.get(p++) & 0x80) == 0) return true;
if (p == limit) return false;
if ((niobuffer.get(p++) & 0x80) == 0) return true;
if (p == limit) return false;
if ((niobuffer.get(p++) & 0x80) == 0) return true;
if (p == limit) return false;
return true;
}
/** Reads the length and string of UTF8 characters, or null. This can read strings written by {@link Output#writeString(String)}
* , {@link Output#writeString(CharSequence)}, and {@link Output#writeAscii(String)}.
* @return May be null. */
public String readString () {
niobuffer.position(position);
int available = require(1);
position++;
int b = niobuffer.get();
if ((b & 0x80) == 0) return readAscii(); // ASCII.
// Null, empty, or UTF8.
int charCount = available >= 5 ? readUtf8Length(b) : readUtf8Length_slow(b);
switch (charCount) {
case 0:
return null;
case 1:
return "";
}
charCount--;
if (chars.length < charCount) chars = new char[charCount];
readUtf8(charCount);
return new String(chars, 0, charCount);
}
private int readUtf8Length (int b) {
int result = b & 0x3F; // Mask all but first 6 bits.
if ((b & 0x40) != 0) { // Bit 7 means another byte, bit 8 means UTF8.
position++;
b = niobuffer.get();
result |= (b & 0x7F) << 6;
if ((b & 0x80) != 0) {
position++;
b = niobuffer.get();
result |= (b & 0x7F) << 13;
if ((b & 0x80) != 0) {
position++;
b = niobuffer.get();
result |= (b & 0x7F) << 20;
if ((b & 0x80) != 0) {
position++;
b = niobuffer.get();
result |= (b & 0x7F) << 27;
}
}
}
}
return result;
}
private int readUtf8Length_slow (int b) {
int result = b & 0x3F; // Mask all but first 6 bits.
if ((b & 0x40) != 0) { // Bit 7 means another byte, bit 8 means UTF8.
require(1);
position++;
b = niobuffer.get();
result |= (b & 0x7F) << 6;
if ((b & 0x80) != 0) {
require(1);
position++;
b = niobuffer.get();
result |= (b & 0x7F) << 13;
if ((b & 0x80) != 0) {
require(1);
position++;
b = niobuffer.get();
result |= (b & 0x7F) << 20;
if ((b & 0x80) != 0) {
require(1);
position++;
b = niobuffer.get();
result |= (b & 0x7F) << 27;
}
}
}
}
return result;
}
private void readUtf8 (int charCount) {
char[] chars = this.chars;
// Try to read 7 bit ASCII chars.
int charIndex = 0;
int count = Math.min(require(1), charCount);
int position = this.position;
int b;
while (charIndex < count) {
position++;
b = niobuffer.get();
if (b < 0) {
position--;
break;
}
chars[charIndex++] = (char)b;
}
this.position = position;
// If buffer didn't hold all chars or any were not ASCII, use slow path for remainder.
if (charIndex < charCount) {
niobuffer.position(position);
readUtf8_slow(charCount, charIndex);
}
}
private void readUtf8_slow (int charCount, int charIndex) {
char[] chars = this.chars;
while (charIndex < charCount) {
if (position == limit) require(1);
position++;
int b = niobuffer.get() & 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 | niobuffer.get() & 0x3F);
break;
case 14:
require(2);
position += 2;
int b2 = niobuffer.get();
int b3 = niobuffer.get();
chars[charIndex] = (char)((b & 0x0F) << 12 | (b2 & 0x3F) << 6 | b3 & 0x3F);
break;
}
charIndex++;
}
}
private String readAscii () {
int end = position;
int start = end - 1;
int limit = this.limit;
int b;
do {
if (end == limit) return readAscii_slow();
end++;
b = niobuffer.get();
} while ((b & 0x80) == 0);
niobuffer.put(end - 1, (byte)(niobuffer.get(end - 1) & 0x7F)); // Mask end of ascii bit.
byte[] tmp = new byte[end - start];
niobuffer.position(start);
niobuffer.get(tmp);
String value = new String(tmp, 0, 0, end - start);
niobuffer.put(end - 1, (byte)(niobuffer.get(end - 1) | 0x80));
position = end;
niobuffer.position(position);
return value;
}
private String readAscii_slow () {
position--; // Re-read the first byte.
// Copy chars currently in buffer.
int charCount = limit - position;
if (charCount > chars.length) chars = new char[charCount * 2];
char[] chars = this.chars;
for (int i = position, ii = 0, n = limit; i < n; i++, ii++)
chars[ii] = (char)niobuffer.get(i);
position = limit;
// Copy additional chars one by one.
while (true) {
require(1);
position++;
int b = niobuffer.get();
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);
break;
}
chars[charCount++] = (char)b;
}
return new String(chars, 0, charCount);
}
/** Reads the length and string of UTF8 characters, or null. This can read strings written by {@link Output#writeString(String)}
* , {@link Output#writeString(CharSequence)}, and {@link Output#writeAscii(String)}.
* @return May be null. */
public StringBuilder readStringBuilder () {
niobuffer.position(position);
int available = require(1);
position++;
int b = niobuffer.get();
if ((b & 0x80) == 0) return new StringBuilder(readAscii()); // ASCII.
// Null, empty, or UTF8.
int charCount = available >= 5 ? readUtf8Length(b) : readUtf8Length_slow(b);
switch (charCount) {
case 0:
return null;
case 1:
return new StringBuilder("");
}
charCount--;
if (chars.length < charCount) chars = new char[charCount];
readUtf8(charCount);
StringBuilder builder = new StringBuilder(charCount);
builder.append(chars, 0, charCount);
return builder;
}
/** Reads a 4 byte float. */
public float readFloat () throws KryoException {
require(4);
position += 4;
return niobuffer.getFloat();
}
/** Reads a 1-5 byte float with reduced precision. */
public float readFloat (float precision, boolean optimizePositive) throws KryoException {
return readInt(optimizePositive) / (float)precision;
}
/** Reads a 2 byte short. */
public short readShort () throws KryoException {
require(2);
position += 2;
return niobuffer.getShort();
}
/** Reads a 2 byte short as an int from 0 to 65535. */
public int readShortUnsigned () throws KryoException {
require(2);
position += 2;
return niobuffer.getShort();
}
/** Reads an 8 byte long. */
public long readLong () throws KryoException {
require(8);
position += 8;
return niobuffer.getLong();
}
/** {@inheritDoc} */
public long readLong (boolean optimizePositive) throws KryoException {
if (varIntsEnabled)
return readVarLong(optimizePositive);
else
return readLong();
}
/** {@inheritDoc} */
public long readVarLong (boolean optimizePositive) throws KryoException {
niobuffer.position(position);
if (require(1) < 9) return readLong_slow(optimizePositive);
position++;
int b = niobuffer.get();
long result = b & 0x7F;
if ((b & 0x80) != 0) {
position++;
b = niobuffer.get();
result |= (b & 0x7F) << 7;
if ((b & 0x80) != 0) {
position++;
b = niobuffer.get();
result |= (b & 0x7F) << 14;
if ((b & 0x80) != 0) {
position++;
b = niobuffer.get();
result |= (b & 0x7F) << 21;
if ((b & 0x80) != 0) {
position++;
b = niobuffer.get();
result |= (long)(b & 0x7F) << 28;
if ((b & 0x80) != 0) {
position++;
b = niobuffer.get();
result |= (long)(b & 0x7F) << 35;
if ((b & 0x80) != 0) {
position++;
b = niobuffer.get();
result |= (long)(b & 0x7F) << 42;
if ((b & 0x80) != 0) {
position++;
b = niobuffer.get();
result |= (long)(b & 0x7F) << 49;
if ((b & 0x80) != 0) {
position++;
b = niobuffer.get();
result |= (long)b << 56;
}
}
}
}
}
}
}
}
if (!optimizePositive) result = (result >>> 1) ^ -(result & 1);
return result;
}
private long readLong_slow (boolean optimizePositive) {
// The buffer is guaranteed to have at least 1 byte.
position++;
int b = niobuffer.get();
long result = b & 0x7F;
if ((b & 0x80) != 0) {
require(1);
position++;
b = niobuffer.get();
result |= (b & 0x7F) << 7;
if ((b & 0x80) != 0) {
require(1);
position++;
b = niobuffer.get();
result |= (b & 0x7F) << 14;
if ((b & 0x80) != 0) {
require(1);
position++;
b = niobuffer.get();
result |= (b & 0x7F) << 21;
if ((b & 0x80) != 0) {
require(1);
position++;
b = niobuffer.get();
result |= (long)(b & 0x7F) << 28;
if ((b & 0x80) != 0) {
require(1);
position++;
b = niobuffer.get();
result |= (long)(b & 0x7F) << 35;
if ((b & 0x80) != 0) {
require(1);
position++;
b = niobuffer.get();
result |= (long)(b & 0x7F) << 42;
if ((b & 0x80) != 0) {
require(1);
position++;
b = niobuffer.get();
result |= (long)(b & 0x7F) << 49;
if ((b & 0x80) != 0) {
require(1);
position++;
b = niobuffer.get();
result |= (long)b << 56;
}
}
}
}
}
}
}
}
if (!optimizePositive) result = (result >>> 1) ^ -(result & 1);
return result;
}
/** Reads a 1 byte boolean. */
public boolean readBoolean () throws KryoException {
require(1);
position++;
return niobuffer.get() == 1 ? true : false;
}
/** Reads a 2 byte char. */
public char readChar () throws KryoException {
require(2);
position += 2;
return niobuffer.getChar();
}
/** Reads an 8 bytes double. */
public double readDouble () throws KryoException {
require(8);
position += 8;
return niobuffer.getDouble();
}
/** Reads a 1-9 byte double with reduced precision. */
public double readDouble (double precision, boolean optimizePositive) throws KryoException {
return readLong(optimizePositive) / (double)precision;
}
// Methods implementing bulk operations on arrays of primitive types
/** Bulk input of an int array. */
public int[] readInts (int length) throws KryoException {
if (capacity - position >= length * 4 && isNativeOrder()) {
int[] array = new int[length];
IntBuffer buf = niobuffer.asIntBuffer();
buf.get(array);
position += length * 4;
niobuffer.position(position);
return array;
} else
return super.readInts(length);
}
/** Bulk input of a long array. */
public long[] readLongs (int length) throws KryoException {
if (capacity - position >= length * 8 && isNativeOrder()) {
long[] array = new long[length];
LongBuffer buf = niobuffer.asLongBuffer();
buf.get(array);
position += length * 8;
niobuffer.position(position);
return array;
} else
return super.readLongs(length);
}
/** Bulk input of a float array. */
public float[] readFloats (int length) throws KryoException {
if (capacity - position >= length * 4 && isNativeOrder()) {
float[] array = new float[length];
FloatBuffer buf = niobuffer.asFloatBuffer();
buf.get(array);
position += length * 4;
niobuffer.position(position);
return array;
} else
return super.readFloats(length);
}
/** Bulk input of a short array. */
public short[] readShorts (int length) throws KryoException {
if (capacity - position >= length * 2 && isNativeOrder()) {
short[] array = new short[length];
ShortBuffer buf = niobuffer.asShortBuffer();
buf.get(array);
position += length * 2;
niobuffer.position(position);
return array;
} else
return super.readShorts(length);
}
/** Bulk input of a char array. */
public char[] readChars (int length) throws KryoException {
if (capacity - position >= length * 2 && isNativeOrder()) {
char[] array = new char[length];
CharBuffer buf = niobuffer.asCharBuffer();
buf.get(array);
position += length * 2;
niobuffer.position(position);
return array;
} else
return super.readChars(length);
}
/** Bulk input of a double array. */
public double[] readDoubles (int length) throws KryoException {
if (capacity - position >= length * 8 && isNativeOrder()) {
double[] array = new double[length];
DoubleBuffer buf = niobuffer.asDoubleBuffer();
buf.get(array);
position += length * 8;
niobuffer.position(position);
return array;
} else
return super.readDoubles(length);
}
private boolean isNativeOrder () {
return byteOrder == nativeOrder;
}
/** Return current setting for variable length encoding of integers
* @return current setting for variable length encoding of integers */
public boolean getVarIntsEnabled () {
return varIntsEnabled;
}
/** Controls if a variable length encoding for integer types should be used when serializers suggest it.
*
* @param varIntsEnabled */
public void setVarIntsEnabled (boolean varIntsEnabled) {
this.varIntsEnabled = varIntsEnabled;
}
}