2021-08-20 03:09:33 +02:00
|
|
|
/*
|
2023-01-24 20:37:56 +01:00
|
|
|
* Copyright 2023 dorkbox, llc
|
2021-08-20 03:09:33 +02:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
2021-08-20 03:53:48 +02:00
|
|
|
package dorkbox.bytes
|
2021-08-20 03:09:33 +02:00
|
|
|
|
2021-08-20 03:53:48 +02:00
|
|
|
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
|
|
|
|
import java.io.IOException
|
|
|
|
import java.io.InputStream
|
2021-08-20 03:09:33 +02:00
|
|
|
|
|
|
|
/**
|
2021-08-20 03:53:48 +02:00
|
|
|
* An [InputStream] which reads data from a [ByteBuf].
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* A read operation against this stream will occur at the `readerIndex`
|
|
|
|
* of its underlying buffer and the `readerIndex` will increase during
|
2021-08-20 03:09:33 +02:00
|
|
|
* the read operation.
|
2021-08-20 03:53:48 +02:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* This stream implements [DataInput] for your convenience.
|
2021-08-20 03:09:33 +02:00
|
|
|
* The endianness of the stream is not always big endian but depends on
|
|
|
|
* the endianness of the underlying buffer.
|
2021-08-20 03:53:48 +02:00
|
|
|
*
|
|
|
|
*
|
2021-08-20 03:09:33 +02:00
|
|
|
* Utility methods are provided for efficiently reading primitive types and strings.
|
2021-08-20 03:53:48 +02:00
|
|
|
*
|
|
|
|
*
|
2021-08-20 03:09:33 +02:00
|
|
|
* Modified from KRYO ByteBufferInput to use ByteBuf instead of ByteBuffer.
|
|
|
|
*/
|
2023-01-25 01:37:04 +01:00
|
|
|
@Suppress("NAME_SHADOWING")
|
2021-08-20 03:53:48 +02:00
|
|
|
class ByteBufInput : Input {
|
2021-08-23 08:14:25 +02:00
|
|
|
companion object {
|
|
|
|
/**
|
|
|
|
* Gets the version number.
|
|
|
|
*/
|
|
|
|
const val version = BytesInfo.version
|
|
|
|
}
|
|
|
|
|
2023-01-24 20:37:56 +01:00
|
|
|
lateinit var byteBuf: ByteBuf
|
2021-08-20 03:53:48 +02:00
|
|
|
private set
|
2021-08-23 08:14:25 +02:00
|
|
|
|
2021-08-20 03:53:48 +02:00
|
|
|
private var initialReaderIndex = 0
|
|
|
|
private var initialWriterIndex = 0
|
|
|
|
private var tempBuffer: ByteArray? = null
|
2021-08-20 03:09:33 +02:00
|
|
|
|
2023-01-24 20:37:56 +01:00
|
|
|
/**
|
|
|
|
* Creates a new Input for reading from a direct [ByteBuf].
|
|
|
|
*
|
2021-08-20 03:09:33 +02:00
|
|
|
* @param bufferSize The size of the buffer. An exception is thrown if more bytes than this are read and
|
2021-08-20 03:53:48 +02:00
|
|
|
* [.fill] does not supply more bytes.
|
|
|
|
*/
|
|
|
|
constructor(bufferSize: Int) {
|
|
|
|
capacity = bufferSize
|
|
|
|
byteBuf = Unpooled.buffer(bufferSize)
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
2023-01-24 20:37:56 +01:00
|
|
|
/**
|
|
|
|
* Creates a new Input for reading from a [ByteBuf] which is filled with the specified bytes.
|
|
|
|
*
|
2021-08-20 03:53:48 +02:00
|
|
|
* @see .setBuffer
|
|
|
|
*/
|
2023-01-24 20:37:56 +01:00
|
|
|
constructor(bytes: ByteArray, offset: Int = 0, count: Int = bytes.size) {
|
2021-08-20 03:53:48 +02:00
|
|
|
setBuffer(Unpooled.wrappedBuffer(bytes, offset, count))
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
|
2023-01-24 20:37:56 +01:00
|
|
|
/**
|
|
|
|
* Creates a new Input for reading from a ByteBuffer.
|
|
|
|
*/
|
|
|
|
constructor(buffer: ByteBuf) {
|
2021-08-20 03:53:48 +02:00
|
|
|
setBuffer(buffer)
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
|
2023-01-24 20:37:56 +01:00
|
|
|
/**
|
|
|
|
* @see Input.Input
|
2021-08-20 03:53:48 +02:00
|
|
|
*/
|
2023-01-24 20:37:56 +01:00
|
|
|
constructor(inputStream: InputStream) : this(4096) {
|
2021-08-20 03:53:48 +02:00
|
|
|
this.inputStream = inputStream
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
|
2023-01-24 20:37:56 +01:00
|
|
|
/**
|
|
|
|
* @see Input.Input
|
2021-08-20 03:53:48 +02:00
|
|
|
*/
|
2023-01-24 20:37:56 +01:00
|
|
|
constructor(inputStream: InputStream, bufferSize: Int) : this(bufferSize) {
|
2021-08-20 03:53:48 +02:00
|
|
|
this.inputStream = inputStream
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
|
2023-01-24 20:37:56 +01:00
|
|
|
/**
|
|
|
|
* Throws [UnsupportedOperationException] because this input uses a ByteBuffer, not a byte[].
|
|
|
|
*
|
2021-08-20 03:53:48 +02:00
|
|
|
* @see .getByteBuf
|
|
|
|
*/
|
2021-08-23 08:14:25 +02:00
|
|
|
@Deprecated("Use getByteBuf() instead",
|
|
|
|
ReplaceWith("getByteBuf()")
|
|
|
|
)
|
2021-08-20 03:53:48 +02:00
|
|
|
override fun getBuffer(): ByteArray {
|
|
|
|
throw UnsupportedOperationException("This input does not used a byte[], see #getByteBuf().")
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
|
2023-01-24 20:37:56 +01:00
|
|
|
/**
|
|
|
|
* Throws [UnsupportedOperationException] because this input uses a ByteBuffer, not a byte[].
|
|
|
|
*
|
2021-08-20 03:53:48 +02:00
|
|
|
* @see .setBuffer
|
|
|
|
*/
|
2021-08-23 08:14:25 +02:00
|
|
|
@Deprecated("Use setByteBuf() instead",
|
2023-01-24 20:37:56 +01:00
|
|
|
ReplaceWith("setBuffer(ByteBuf)")
|
2021-08-23 08:14:25 +02:00
|
|
|
)
|
2021-08-20 03:53:48 +02:00
|
|
|
override fun setBuffer(bytes: ByteArray) {
|
2023-01-24 20:37:56 +01:00
|
|
|
throw UnsupportedOperationException("This input does not used a byte[], see #setBuffer(ByteBuf).")
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
|
2023-01-24 20:37:56 +01:00
|
|
|
/**
|
|
|
|
* Throws [UnsupportedOperationException] because this input uses a ByteBuffer, not a byte[].
|
|
|
|
*
|
2021-08-20 03:53:48 +02:00
|
|
|
* @see .setBuffer
|
|
|
|
*/
|
2023-01-24 20:37:56 +01:00
|
|
|
@Deprecated("This input does not used a byte[], see #setByteBuf().",
|
|
|
|
ReplaceWith("setBuffer(ByteBuf)")
|
|
|
|
)
|
2021-08-20 03:53:48 +02:00
|
|
|
override fun setBuffer(bytes: ByteArray, offset: Int, count: Int) {
|
2023-01-24 20:37:56 +01:00
|
|
|
throw UnsupportedOperationException("This input does not used a byte[], see #setBuffer().")
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
|
2023-01-24 20:37:56 +01:00
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
*
|
2021-08-20 03:09:33 +02:00
|
|
|
* The position, limit, and capacity are set to match the specified buffer. The total is reset. The
|
2023-01-24 20:37:56 +01:00
|
|
|
* [InputStream][.setInputStream] is set to null.
|
|
|
|
*/
|
|
|
|
fun setBuffer(buffer: ByteBuf) {
|
2021-08-20 03:53:48 +02:00
|
|
|
byteBuf = buffer
|
2023-01-24 20:37:56 +01:00
|
|
|
initialReaderIndex = byteBuf.readerIndex() // where the object starts...
|
|
|
|
initialWriterIndex = byteBuf.writerIndex() // where the object ends...
|
2021-08-20 03:53:48 +02:00
|
|
|
position = initialReaderIndex
|
|
|
|
limit = initialWriterIndex
|
|
|
|
capacity = buffer.capacity()
|
|
|
|
total = 0
|
|
|
|
inputStream = null
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun setInputStream(inputStream: InputStream) {
|
|
|
|
this.inputStream = inputStream
|
|
|
|
limit = 0
|
|
|
|
reset()
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun reset() {
|
|
|
|
super.reset()
|
2023-01-24 20:37:56 +01:00
|
|
|
byteBuf.setIndex(initialReaderIndex, initialWriterIndex)
|
2021-08-20 03:53:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Fills the buffer with more bytes. The default implementation reads from the [InputStream][.getInputStream], if set.
|
|
|
|
* Can be overridden to fill the bytes from another source. */
|
|
|
|
@Throws(KryoException::class)
|
|
|
|
protected fun fill(buffer: ByteBuf?, offset: Int, count: Int): Int {
|
|
|
|
var count = count
|
|
|
|
return if (inputStream == null) -1 else try {
|
|
|
|
if (tempBuffer == null) tempBuffer = ByteArray(2048)
|
|
|
|
buffer!!.readerIndex(offset)
|
|
|
|
var total = 0
|
2021-08-20 03:09:33 +02:00
|
|
|
while (count > 0) {
|
2021-08-20 03:53:48 +02:00
|
|
|
val read = inputStream.read(tempBuffer, 0, Math.min(tempBuffer!!.size, count))
|
2021-08-20 03:09:33 +02:00
|
|
|
if (read == -1) {
|
2021-08-20 03:53:48 +02:00
|
|
|
if (total == 0) return -1
|
|
|
|
break
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
2021-08-20 03:53:48 +02:00
|
|
|
buffer.writeBytes(tempBuffer, 0, read)
|
|
|
|
count -= read
|
|
|
|
total += read
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
2021-08-20 03:53:48 +02:00
|
|
|
buffer.readerIndex(offset)
|
|
|
|
total
|
|
|
|
} catch (ex: IOException) {
|
|
|
|
throw KryoException(ex)
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-20 03:53:48 +02:00
|
|
|
@Throws(KryoException::class)
|
|
|
|
override fun require(required: Int): Int {
|
|
|
|
var remaining = limit - position
|
|
|
|
if (remaining >= required) return remaining
|
|
|
|
if (required > capacity) throw KryoException("Buffer too small: capacity: $capacity, required: $required")
|
|
|
|
val count: Int
|
2021-08-20 03:09:33 +02:00
|
|
|
// Try to fill the buffer.
|
|
|
|
if (remaining > 0) {
|
2021-08-20 03:53:48 +02:00
|
|
|
count = fill(byteBuf, limit, capacity - limit)
|
|
|
|
if (count == -1) throw KryoException("Buffer underflow.")
|
|
|
|
remaining += count
|
2021-08-20 03:09:33 +02:00
|
|
|
if (remaining >= required) {
|
2021-08-20 03:53:48 +02:00
|
|
|
limit += count
|
|
|
|
return remaining
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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);
|
2021-08-20 03:53:48 +02:00
|
|
|
return remaining
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Fills the buffer with at least the number of bytes specified, if possible.
|
|
|
|
* @param optional Must be > 0.
|
2021-08-20 03:53:48 +02:00
|
|
|
* @return the number of bytes remaining, but not more than optional, or -1 if [.fill] is unable to
|
|
|
|
* provide more bytes.
|
|
|
|
*/
|
|
|
|
@Throws(KryoException::class)
|
|
|
|
override fun optional(optional: Int): Int {
|
|
|
|
var optional = optional
|
|
|
|
var remaining = limit - position
|
|
|
|
if (remaining >= optional) return optional
|
|
|
|
optional = Math.min(optional, capacity)
|
2021-08-20 03:09:33 +02:00
|
|
|
|
|
|
|
// Try to fill the buffer.
|
2021-08-20 03:53:48 +02:00
|
|
|
val count = fill(byteBuf, limit, capacity - limit)
|
|
|
|
if (count == -1) return if (remaining == 0) -1 else Math.min(remaining, optional)
|
|
|
|
remaining += count
|
2021-08-20 03:09:33 +02:00
|
|
|
if (remaining >= optional) {
|
2021-08-20 03:53:48 +02:00
|
|
|
limit += count
|
|
|
|
return optional
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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);
|
2021-08-20 03:53:48 +02:00
|
|
|
return if (remaining == 0) -1 else Math.min(remaining, optional)
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// InputStream:
|
2021-08-20 03:53:48 +02:00
|
|
|
@Throws(KryoException::class)
|
|
|
|
override fun read(): Int {
|
|
|
|
if (optional(1) <= 0) return -1
|
|
|
|
position++
|
2023-01-24 20:37:56 +01:00
|
|
|
return byteBuf.readByte().toInt() and 0xFF
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
|
2021-08-20 03:53:48 +02:00
|
|
|
@Throws(KryoException::class)
|
|
|
|
override fun read(bytes: ByteArray): Int {
|
|
|
|
return read(bytes, 0, bytes.size)
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
|
2021-08-20 03:53:48 +02:00
|
|
|
@Throws(KryoException::class)
|
|
|
|
override fun read(bytes: ByteArray, offset: Int, count: Int): Int {
|
|
|
|
var offset = offset
|
|
|
|
var count = count
|
|
|
|
requireNotNull(bytes) { "bytes cannot be null." }
|
|
|
|
val startingCount = count
|
|
|
|
var copyCount = Math.min(limit - position, count)
|
2021-08-20 03:09:33 +02:00
|
|
|
while (true) {
|
2023-01-24 20:37:56 +01:00
|
|
|
byteBuf.getBytes(position, bytes, offset, copyCount)
|
2021-08-20 03:53:48 +02:00
|
|
|
position += copyCount
|
|
|
|
count -= copyCount
|
|
|
|
if (count == 0) break
|
|
|
|
offset += copyCount
|
|
|
|
copyCount = optional(count)
|
2021-08-20 03:09:33 +02:00
|
|
|
if (copyCount == -1) {
|
|
|
|
// End of data.
|
2021-08-20 03:53:48 +02:00
|
|
|
if (startingCount == count) return -1
|
|
|
|
break
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
2021-08-20 03:53:48 +02:00
|
|
|
if (position == limit) break
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
2021-08-20 03:53:48 +02:00
|
|
|
return startingCount - count
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
|
2021-08-20 03:53:48 +02:00
|
|
|
override fun setPosition(position: Int) {
|
|
|
|
this.position = position
|
2023-01-24 20:37:56 +01:00
|
|
|
byteBuf.readerIndex(position)
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
|
2021-08-20 03:53:48 +02:00
|
|
|
override fun setLimit(limit: Int) {
|
|
|
|
this.limit = limit
|
2023-01-24 20:37:56 +01:00
|
|
|
byteBuf.writerIndex(limit)
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
|
2021-08-20 03:53:48 +02:00
|
|
|
@Throws(KryoException::class)
|
|
|
|
override fun skip(count: Int) {
|
|
|
|
super.skip(count)
|
2023-01-24 20:37:56 +01:00
|
|
|
byteBuf.readerIndex(position)
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
|
2021-08-20 03:53:48 +02:00
|
|
|
@Throws(KryoException::class)
|
|
|
|
override fun skip(count: Long): Long {
|
|
|
|
var remaining = count
|
2021-08-20 03:09:33 +02:00
|
|
|
while (remaining > 0) {
|
2021-08-20 03:53:48 +02:00
|
|
|
val skip = Math.min(Util.maxArraySize.toLong(), remaining).toInt()
|
|
|
|
skip(skip)
|
|
|
|
remaining -= skip.toLong()
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
2021-08-20 03:53:48 +02:00
|
|
|
return count
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
|
2021-08-20 03:53:48 +02:00
|
|
|
@Throws(KryoException::class)
|
|
|
|
override fun close() {
|
2021-08-20 03:09:33 +02:00
|
|
|
if (inputStream != null) {
|
|
|
|
try {
|
2021-08-20 03:53:48 +02:00
|
|
|
inputStream.close()
|
|
|
|
} catch (ignored: IOException) {
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// byte:
|
2021-08-20 03:53:48 +02:00
|
|
|
@Throws(KryoException::class)
|
|
|
|
override fun readByte(): Byte {
|
|
|
|
if (position == limit) require(1)
|
|
|
|
position++
|
2023-01-24 20:37:56 +01:00
|
|
|
return byteBuf.readByte()
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
|
2021-08-20 03:53:48 +02:00
|
|
|
@Throws(KryoException::class)
|
|
|
|
override fun readByteUnsigned(): Int {
|
|
|
|
if (position == limit) require(1)
|
|
|
|
position++
|
2023-01-24 20:37:56 +01:00
|
|
|
return byteBuf.readByte().toInt() and 0xFF
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
|
2021-08-20 03:53:48 +02:00
|
|
|
@Throws(KryoException::class)
|
|
|
|
override fun readBytes(length: Int): ByteArray {
|
|
|
|
val bytes = ByteArray(length)
|
|
|
|
readBytes(bytes, 0, length)
|
|
|
|
return bytes
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
|
2021-08-20 03:53:48 +02:00
|
|
|
@Throws(KryoException::class)
|
|
|
|
override fun readBytes(bytes: ByteArray, offset: Int, count: Int) {
|
|
|
|
var offset = offset
|
|
|
|
var count = count
|
|
|
|
requireNotNull(bytes) { "bytes cannot be null." }
|
|
|
|
var copyCount = Math.min(limit - position, count)
|
2021-08-20 03:09:33 +02:00
|
|
|
while (true) {
|
2023-01-24 20:37:56 +01:00
|
|
|
byteBuf.readBytes(bytes, offset, copyCount)
|
2021-08-20 03:53:48 +02:00
|
|
|
position += copyCount
|
|
|
|
count -= copyCount
|
|
|
|
if (count == 0) break
|
|
|
|
offset += copyCount
|
|
|
|
copyCount = Math.min(count, capacity)
|
|
|
|
require(copyCount)
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// int:
|
2021-08-20 03:53:48 +02:00
|
|
|
@Throws(KryoException::class)
|
|
|
|
override fun readInt(): Int {
|
|
|
|
require(4)
|
|
|
|
position += 4
|
2023-01-24 20:37:56 +01:00
|
|
|
return byteBuf.readInt()
|
2021-08-20 03:53:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Throws(KryoException::class)
|
|
|
|
override fun readVarInt(optimizePositive: Boolean): Int {
|
|
|
|
if (require(1) < 5) return readVarInt_slow(optimizePositive)
|
2023-01-24 20:37:56 +01:00
|
|
|
val byteBuf = byteBuf
|
2021-08-20 03:53:48 +02:00
|
|
|
var b = byteBuf.readByte().toInt()
|
|
|
|
var result = b and 0x7F
|
|
|
|
if (b and 0x80 != 0) {
|
|
|
|
b = byteBuf.readByte().toInt()
|
|
|
|
result = result or (b and 0x7F shl 7)
|
|
|
|
if (b and 0x80 != 0) {
|
|
|
|
b = byteBuf.readByte().toInt()
|
|
|
|
result = result or (b and 0x7F shl 14)
|
|
|
|
if (b and 0x80 != 0) {
|
|
|
|
b = byteBuf.readByte().toInt()
|
|
|
|
result = result or (b and 0x7F shl 21)
|
|
|
|
if (b and 0x80 != 0) {
|
|
|
|
b = byteBuf.readByte().toInt()
|
|
|
|
result = result or (b and 0x7F shl 28)
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-08-20 03:53:48 +02:00
|
|
|
position = byteBuf.readerIndex()
|
|
|
|
return if (optimizePositive) result else result ushr 1 xor -(result and 1)
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
|
2021-08-20 03:53:48 +02:00
|
|
|
private fun readVarInt_slow(optimizePositive: Boolean): Int {
|
2021-08-20 03:09:33 +02:00
|
|
|
// The buffer is guaranteed to have at least 1 byte.
|
2021-08-20 03:53:48 +02:00
|
|
|
position++
|
2023-01-24 20:37:56 +01:00
|
|
|
val byteBuf = byteBuf
|
2021-08-20 03:53:48 +02:00
|
|
|
var b = byteBuf.readByte().toInt()
|
|
|
|
var result = b and 0x7F
|
|
|
|
if (b and 0x80 != 0) {
|
|
|
|
if (position == limit) require(1)
|
|
|
|
position++
|
|
|
|
b = byteBuf.readByte().toInt()
|
|
|
|
result = result or (b and 0x7F shl 7)
|
|
|
|
if (b and 0x80 != 0) {
|
|
|
|
if (position == limit) require(1)
|
|
|
|
position++
|
|
|
|
b = byteBuf.readByte().toInt()
|
|
|
|
result = result or (b and 0x7F shl 14)
|
|
|
|
if (b and 0x80 != 0) {
|
|
|
|
if (position == limit) require(1)
|
|
|
|
position++
|
|
|
|
b = byteBuf.readByte().toInt()
|
|
|
|
result = result or (b and 0x7F shl 21)
|
|
|
|
if (b and 0x80 != 0) {
|
|
|
|
if (position == limit) require(1)
|
|
|
|
position++
|
|
|
|
b = byteBuf.readByte().toInt()
|
|
|
|
result = result or (b and 0x7F shl 28)
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-08-20 03:53:48 +02:00
|
|
|
return if (optimizePositive) result else result ushr 1 xor -(result and 1)
|
|
|
|
}
|
|
|
|
|
|
|
|
@Throws(KryoException::class)
|
|
|
|
override fun canReadVarInt(): Boolean {
|
|
|
|
if (limit - position >= 5) return true
|
|
|
|
if (optional(5) <= 0) return false
|
|
|
|
var p = position
|
|
|
|
val limit = limit
|
2023-01-24 20:37:56 +01:00
|
|
|
val byteBuf = byteBuf
|
2021-08-20 03:53:48 +02:00
|
|
|
if (byteBuf.getByte(p++).toInt() and 0x80 == 0) return true
|
|
|
|
if (p == limit) return false
|
|
|
|
if (byteBuf.getByte(p++).toInt() and 0x80 == 0) return true
|
|
|
|
if (p == limit) return false
|
|
|
|
if (byteBuf.getByte(p++).toInt() and 0x80 == 0) return true
|
|
|
|
if (p == limit) return false
|
|
|
|
if (byteBuf.getByte(p++).toInt() and 0x80 == 0) return true
|
|
|
|
return if (p == limit) false else true
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Reads the boolean part of a varint flag. The position is not advanced, [.readVarIntFlag] should be used to
|
|
|
|
* advance the position. */
|
|
|
|
override fun readVarIntFlag(): Boolean {
|
|
|
|
if (position == limit) require(1)
|
2023-01-24 20:37:56 +01:00
|
|
|
return byteBuf.getByte(position).toInt() and 0x80 != 0
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/** 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
|
2021-08-20 03:53:48 +02:00
|
|
|
* first with [.readVarIntFlag]. */
|
|
|
|
override fun readVarIntFlag(optimizePositive: Boolean): Int {
|
|
|
|
if (require(1) < 5) return readVarIntFlag_slow(optimizePositive)
|
|
|
|
val byteBuf = byteBuf
|
2023-01-24 20:37:56 +01:00
|
|
|
var b = byteBuf.readByte().toInt()
|
2021-08-20 03:53:48 +02:00
|
|
|
var result = b and 0x3F // Mask first 6 bits.
|
|
|
|
if (b and 0x40 != 0) { // Bit 7 means another byte, bit 8 means UTF8.
|
|
|
|
b = byteBuf.readByte().toInt()
|
|
|
|
result = result or (b and 0x7F shl 6)
|
|
|
|
if (b and 0x80 != 0) {
|
|
|
|
b = byteBuf.readByte().toInt()
|
|
|
|
result = result or (b and 0x7F shl 13)
|
|
|
|
if (b and 0x80 != 0) {
|
|
|
|
b = byteBuf.readByte().toInt()
|
|
|
|
result = result or (b and 0x7F shl 20)
|
|
|
|
if (b and 0x80 != 0) {
|
|
|
|
b = byteBuf.readByte().toInt()
|
|
|
|
result = result or (b and 0x7F shl 27)
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-08-20 03:53:48 +02:00
|
|
|
position = byteBuf.readerIndex()
|
|
|
|
return if (optimizePositive) result else result ushr 1 xor -(result and 1)
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
|
2021-08-20 03:53:48 +02:00
|
|
|
private fun readVarIntFlag_slow(optimizePositive: Boolean): Int {
|
2021-08-20 03:09:33 +02:00
|
|
|
// The buffer is guaranteed to have at least 1 byte.
|
2021-08-20 03:53:48 +02:00
|
|
|
position++
|
2023-01-24 20:37:56 +01:00
|
|
|
var b = byteBuf.readByte().toInt()
|
2021-08-20 03:53:48 +02:00
|
|
|
var result = b and 0x3F
|
|
|
|
if (b and 0x40 != 0) {
|
|
|
|
if (position == limit) require(1)
|
|
|
|
position++
|
|
|
|
val byteBuf = byteBuf
|
2023-01-24 20:37:56 +01:00
|
|
|
b = byteBuf.readByte().toInt()
|
2021-08-20 03:53:48 +02:00
|
|
|
result = result or (b and 0x7F shl 6)
|
|
|
|
if (b and 0x80 != 0) {
|
|
|
|
if (position == limit) require(1)
|
|
|
|
position++
|
|
|
|
b = byteBuf.readByte().toInt()
|
|
|
|
result = result or (b and 0x7F shl 13)
|
|
|
|
if (b and 0x80 != 0) {
|
|
|
|
if (position == limit) require(1)
|
|
|
|
position++
|
|
|
|
b = byteBuf.readByte().toInt()
|
|
|
|
result = result or (b and 0x7F shl 20)
|
|
|
|
if (b and 0x80 != 0) {
|
|
|
|
if (position == limit) require(1)
|
|
|
|
position++
|
|
|
|
b = byteBuf.readByte().toInt()
|
|
|
|
result = result or (b and 0x7F shl 27)
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-08-20 03:53:48 +02:00
|
|
|
return if (optimizePositive) result else result ushr 1 xor -(result and 1)
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// long:
|
2021-08-20 03:53:48 +02:00
|
|
|
@Throws(KryoException::class)
|
|
|
|
override fun readLong(): Long {
|
|
|
|
require(8)
|
|
|
|
position += 8
|
2023-01-24 20:37:56 +01:00
|
|
|
return byteBuf.readLong()
|
2021-08-20 03:53:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Throws(KryoException::class)
|
|
|
|
override fun readVarLong(optimizePositive: Boolean): Long {
|
|
|
|
if (require(1) < 9) return readVarLong_slow(optimizePositive)
|
2023-01-24 20:37:56 +01:00
|
|
|
val byteBuf = byteBuf
|
2021-08-20 03:53:48 +02:00
|
|
|
var b = byteBuf.readByte().toInt()
|
|
|
|
var result = (b and 0x7F).toLong()
|
|
|
|
if (b and 0x80 != 0) {
|
|
|
|
b = byteBuf.readByte().toInt()
|
|
|
|
result = result or (b and 0x7F shl 7).toLong()
|
|
|
|
if (b and 0x80 != 0) {
|
|
|
|
b = byteBuf.readByte().toInt()
|
|
|
|
result = result or (b and 0x7F shl 14).toLong()
|
|
|
|
if (b and 0x80 != 0) {
|
|
|
|
b = byteBuf.readByte().toInt()
|
|
|
|
result = result or (b and 0x7F shl 21).toLong()
|
|
|
|
if (b and 0x80 != 0) {
|
|
|
|
b = byteBuf.readByte().toInt()
|
|
|
|
result = result or ((b and 0x7F).toLong() shl 28)
|
|
|
|
if (b and 0x80 != 0) {
|
|
|
|
b = byteBuf.readByte().toInt()
|
|
|
|
result = result or ((b and 0x7F).toLong() shl 35)
|
|
|
|
if (b and 0x80 != 0) {
|
|
|
|
b = byteBuf.readByte().toInt()
|
|
|
|
result = result or ((b and 0x7F).toLong() shl 42)
|
|
|
|
if (b and 0x80 != 0) {
|
|
|
|
b = byteBuf.readByte().toInt()
|
|
|
|
result = result or ((b and 0x7F).toLong() shl 49)
|
|
|
|
if (b and 0x80 != 0) {
|
|
|
|
b = byteBuf.readByte().toInt()
|
|
|
|
result = result or (b.toLong() shl 56)
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-08-20 03:53:48 +02:00
|
|
|
position = byteBuf.readerIndex()
|
|
|
|
return if (optimizePositive) result else result ushr 1 xor -(result and 1)
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
|
2021-08-20 03:53:48 +02:00
|
|
|
private fun readVarLong_slow(optimizePositive: Boolean): Long {
|
2021-08-20 03:09:33 +02:00
|
|
|
// The buffer is guaranteed to have at least 1 byte.
|
2021-08-20 03:53:48 +02:00
|
|
|
position++
|
2023-01-24 20:37:56 +01:00
|
|
|
val byteBuf = byteBuf
|
2021-08-20 03:53:48 +02:00
|
|
|
var b = byteBuf.readByte().toInt()
|
|
|
|
var result = (b and 0x7F).toLong()
|
|
|
|
if (b and 0x80 != 0) {
|
|
|
|
if (position == limit) require(1)
|
|
|
|
position++
|
|
|
|
b = byteBuf.readByte().toInt()
|
|
|
|
result = result or (b and 0x7F shl 7).toLong()
|
|
|
|
if (b and 0x80 != 0) {
|
|
|
|
if (position == limit) require(1)
|
|
|
|
position++
|
|
|
|
b = byteBuf.readByte().toInt()
|
|
|
|
result = result or (b and 0x7F shl 14).toLong()
|
|
|
|
if (b and 0x80 != 0) {
|
|
|
|
if (position == limit) require(1)
|
|
|
|
position++
|
|
|
|
b = byteBuf.readByte().toInt()
|
|
|
|
result = result or (b and 0x7F shl 21).toLong()
|
|
|
|
if (b and 0x80 != 0) {
|
|
|
|
if (position == limit) require(1)
|
|
|
|
position++
|
|
|
|
b = byteBuf.readByte().toInt()
|
|
|
|
result = result or ((b and 0x7F).toLong() shl 28)
|
|
|
|
if (b and 0x80 != 0) {
|
|
|
|
if (position == limit) require(1)
|
|
|
|
position++
|
|
|
|
b = byteBuf.readByte().toInt()
|
|
|
|
result = result or ((b and 0x7F).toLong() shl 35)
|
|
|
|
if (b and 0x80 != 0) {
|
|
|
|
if (position == limit) require(1)
|
|
|
|
position++
|
|
|
|
b = byteBuf.readByte().toInt()
|
|
|
|
result = result or ((b and 0x7F).toLong() shl 42)
|
|
|
|
if (b and 0x80 != 0) {
|
|
|
|
if (position == limit) require(1)
|
|
|
|
position++
|
|
|
|
b = byteBuf.readByte().toInt()
|
|
|
|
result = result or ((b and 0x7F).toLong() shl 49)
|
|
|
|
if (b and 0x80 != 0) {
|
|
|
|
if (position == limit) require(1)
|
|
|
|
position++
|
|
|
|
b = byteBuf.readByte().toInt()
|
|
|
|
result = result or (b.toLong() shl 56)
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-08-20 03:53:48 +02:00
|
|
|
return if (optimizePositive) result else result ushr 1 xor -(result and 1)
|
|
|
|
}
|
|
|
|
|
|
|
|
@Throws(KryoException::class)
|
|
|
|
override fun canReadVarLong(): Boolean {
|
|
|
|
if (limit - position >= 9) return true
|
|
|
|
if (optional(5) <= 0) return false
|
|
|
|
var p = position
|
|
|
|
val limit = limit
|
|
|
|
val byteBuf = byteBuf
|
2023-01-24 20:37:56 +01:00
|
|
|
if (byteBuf.getByte(p++).toInt() and 0x80 == 0) return true
|
2021-08-20 03:53:48 +02:00
|
|
|
if (p == limit) return false
|
|
|
|
if (byteBuf.getByte(p++).toInt() and 0x80 == 0) return true
|
|
|
|
if (p == limit) return false
|
|
|
|
if (byteBuf.getByte(p++).toInt() and 0x80 == 0) return true
|
|
|
|
if (p == limit) return false
|
|
|
|
if (byteBuf.getByte(p++).toInt() and 0x80 == 0) return true
|
|
|
|
if (p == limit) return false
|
|
|
|
if (byteBuf.getByte(p++).toInt() and 0x80 == 0) return true
|
|
|
|
if (p == limit) return false
|
|
|
|
if (byteBuf.getByte(p++).toInt() and 0x80 == 0) return true
|
|
|
|
if (p == limit) return false
|
|
|
|
if (byteBuf.getByte(p++).toInt() and 0x80 == 0) return true
|
|
|
|
if (p == limit) return false
|
|
|
|
if (byteBuf.getByte(p++).toInt() and 0x80 == 0) return true
|
|
|
|
return if (p == limit) false else true
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// float:
|
2021-08-20 03:53:48 +02:00
|
|
|
@Throws(KryoException::class)
|
|
|
|
override fun readFloat(): Float {
|
|
|
|
require(4)
|
|
|
|
val p = position
|
|
|
|
position = p + 4
|
2023-01-24 20:37:56 +01:00
|
|
|
return byteBuf.readFloat()
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// double:
|
2021-08-20 03:53:48 +02:00
|
|
|
@Throws(KryoException::class)
|
|
|
|
override fun readDouble(): Double {
|
|
|
|
require(8)
|
|
|
|
val p = position
|
|
|
|
position = p + 8
|
2023-01-24 20:37:56 +01:00
|
|
|
return byteBuf.readDouble()
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// boolean:
|
2021-08-20 03:53:48 +02:00
|
|
|
@Throws(KryoException::class)
|
|
|
|
override fun readBoolean(): Boolean {
|
|
|
|
if (position == limit) require(1)
|
|
|
|
position++
|
2023-01-24 20:37:56 +01:00
|
|
|
return if (byteBuf.readByte().toInt() == 1) true else false
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// short:
|
2021-08-20 03:53:48 +02:00
|
|
|
@Throws(KryoException::class)
|
|
|
|
override fun readShort(): Short {
|
|
|
|
require(2)
|
|
|
|
position += 2
|
2023-01-24 20:37:56 +01:00
|
|
|
return byteBuf.readShort()
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
|
2021-08-20 03:53:48 +02:00
|
|
|
@Throws(KryoException::class)
|
|
|
|
override fun readShortUnsigned(): Int {
|
|
|
|
require(2)
|
|
|
|
position += 2
|
2023-01-24 20:37:56 +01:00
|
|
|
return byteBuf.readUnsignedShort()
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// char:
|
2021-08-20 03:53:48 +02:00
|
|
|
@Throws(KryoException::class)
|
|
|
|
override fun readChar(): Char {
|
|
|
|
require(2)
|
|
|
|
position += 2
|
2023-01-24 20:37:56 +01:00
|
|
|
return byteBuf.readChar()
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// String:
|
2021-08-20 03:53:48 +02:00
|
|
|
override fun readString(): String? {
|
|
|
|
if (!readVarIntFlag()) return readAsciiString() // ASCII.
|
2021-08-20 03:09:33 +02:00
|
|
|
// Null, empty, or UTF8.
|
2021-08-20 03:53:48 +02:00
|
|
|
var charCount = readVarIntFlag(true)
|
|
|
|
when (charCount) {
|
|
|
|
0 -> return null
|
|
|
|
1 -> return ""
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
2021-08-20 03:53:48 +02:00
|
|
|
|
|
|
|
charCount-- // make count adjustment
|
|
|
|
readUtf8Chars(charCount)
|
|
|
|
return String(chars, 0, charCount)
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
|
2021-08-20 03:53:48 +02:00
|
|
|
override fun readStringBuilder(): StringBuilder? {
|
|
|
|
if (!readVarIntFlag()) return StringBuilder(readAsciiString()) // ASCII.
|
2021-08-20 03:09:33 +02:00
|
|
|
// Null, empty, or UTF8.
|
2021-08-20 03:53:48 +02:00
|
|
|
var charCount = readVarIntFlag(true)
|
|
|
|
when (charCount) {
|
|
|
|
0 -> return null
|
|
|
|
1 -> return StringBuilder("")
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
2021-08-20 03:53:48 +02:00
|
|
|
charCount--
|
|
|
|
readUtf8Chars(charCount)
|
|
|
|
val builder = StringBuilder(charCount)
|
|
|
|
builder.append(chars, 0, charCount)
|
|
|
|
return builder
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
|
2021-08-20 03:53:48 +02:00
|
|
|
private fun readUtf8Chars(charCount: Int) {
|
|
|
|
if (chars.size < charCount) chars = CharArray(charCount)
|
|
|
|
val chars = chars
|
2021-08-20 03:09:33 +02:00
|
|
|
// Try to read 7 bit ASCII chars.
|
2023-01-24 20:37:56 +01:00
|
|
|
val byteBuf = byteBuf
|
2021-08-20 03:53:48 +02:00
|
|
|
var charIndex = 0
|
|
|
|
val count = require(1).coerceAtMost(charCount)
|
2021-08-20 03:09:33 +02:00
|
|
|
while (charIndex < count) {
|
2021-08-20 03:53:48 +02:00
|
|
|
val b = byteBuf.readByte().toInt()
|
|
|
|
if (b < 0) break
|
|
|
|
chars[charIndex++] = b.toChar()
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
2021-08-20 03:53:48 +02:00
|
|
|
position += charIndex
|
|
|
|
|
2021-08-20 03:09:33 +02:00
|
|
|
// If buffer didn't hold all chars or any were not ASCII, use slow path for remainder.
|
|
|
|
if (charIndex < charCount) {
|
2021-08-20 03:53:48 +02:00
|
|
|
byteBuf.readerIndex(position)
|
|
|
|
readUtf8Chars_slow(charCount, charIndex)
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-20 03:53:48 +02:00
|
|
|
private fun readUtf8Chars_slow(charCount: Int, charIndex: Int) {
|
|
|
|
var index = charIndex
|
2023-01-24 20:37:56 +01:00
|
|
|
val byteBuf = byteBuf
|
2021-08-20 03:53:48 +02:00
|
|
|
val chars = chars
|
|
|
|
|
|
|
|
while (index < charCount) {
|
|
|
|
if (position == limit) require(1)
|
|
|
|
|
|
|
|
position++
|
|
|
|
val b: Int = byteBuf.readByte().toInt() and 0xFF
|
|
|
|
when (b shr 4) {
|
|
|
|
0, 1, 2, 3, 4, 5, 6, 7 -> chars[index] = b.toChar()
|
|
|
|
12, 13 -> {
|
|
|
|
if (position == limit) require(1)
|
|
|
|
position++
|
|
|
|
chars[index] = (b and 0x1F shl 6 or (byteBuf.readByte().toInt() and 0x3F)).toChar()
|
|
|
|
}
|
|
|
|
14 -> {
|
|
|
|
require(2)
|
|
|
|
position += 2
|
|
|
|
val b2 = byteBuf.readByte().toInt()
|
|
|
|
val b3 = byteBuf.readByte().toInt()
|
|
|
|
chars[index] = (b and 0x0F shl 12 or (b2 and 0x3F shl 6) or (b3 and 0x3F)).toChar()
|
|
|
|
}
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
2021-08-20 03:53:48 +02:00
|
|
|
index++
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-20 03:53:48 +02:00
|
|
|
private fun readAsciiString(): String {
|
|
|
|
val chars = chars
|
|
|
|
val byteBuf = byteBuf
|
|
|
|
var charCount = 0
|
|
|
|
val n = Math.min(chars.size, limit - position)
|
|
|
|
while (charCount < n) {
|
2023-01-24 20:37:56 +01:00
|
|
|
val b = byteBuf.readByte().toInt()
|
2021-08-20 03:53:48 +02:00
|
|
|
if (b and 0x80 == 0x80) {
|
|
|
|
position = byteBuf.readerIndex()
|
|
|
|
chars[charCount] = (b and 0x7F).toChar()
|
|
|
|
return String(chars, 0, charCount + 1)
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
2021-08-20 03:53:48 +02:00
|
|
|
chars[charCount] = b.toChar()
|
|
|
|
charCount++
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
2023-01-24 20:37:56 +01:00
|
|
|
position = byteBuf.readerIndex()
|
2021-08-20 03:53:48 +02:00
|
|
|
return readAscii_slow(charCount)
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
|
2021-08-20 03:53:48 +02:00
|
|
|
private fun readAscii_slow(charCount: Int): String {
|
|
|
|
var charCount = charCount
|
|
|
|
var chars = chars
|
|
|
|
val byteBuf = byteBuf
|
2021-08-20 03:09:33 +02:00
|
|
|
while (true) {
|
2021-08-20 03:53:48 +02:00
|
|
|
if (position == limit) require(1)
|
|
|
|
position++
|
2023-01-24 20:37:56 +01:00
|
|
|
val b = byteBuf.readByte().toInt()
|
2021-08-20 03:53:48 +02:00
|
|
|
if (charCount == chars.size) {
|
|
|
|
val newChars = CharArray(charCount * 2)
|
|
|
|
System.arraycopy(chars, 0, newChars, 0, charCount)
|
|
|
|
chars = newChars
|
|
|
|
this.chars = newChars
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
2021-08-20 03:53:48 +02:00
|
|
|
if (b and 0x80 == 0x80) {
|
|
|
|
chars[charCount] = (b and 0x7F).toChar()
|
|
|
|
return String(chars, 0, charCount + 1)
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
2021-08-20 03:53:48 +02:00
|
|
|
chars[charCount++] = b.toChar()
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Primitive arrays:
|
2021-08-20 03:53:48 +02:00
|
|
|
@Throws(KryoException::class)
|
|
|
|
override fun readInts(length: Int): IntArray {
|
|
|
|
val array = IntArray(length)
|
|
|
|
if (optional(length shl 2) == length shl 2) {
|
|
|
|
val byteBuf = byteBuf
|
|
|
|
for (i in 0 until length) {
|
2023-01-24 20:37:56 +01:00
|
|
|
array[i] = byteBuf.readInt()
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
2023-01-24 20:37:56 +01:00
|
|
|
position = byteBuf.readerIndex()
|
2021-08-20 03:09:33 +02:00
|
|
|
} else {
|
2021-08-20 03:53:48 +02:00
|
|
|
for (i in 0 until length) array[i] = readInt()
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
2021-08-20 03:53:48 +02:00
|
|
|
return array
|
|
|
|
}
|
|
|
|
|
|
|
|
@Throws(KryoException::class)
|
|
|
|
override fun readLongs(length: Int): LongArray {
|
|
|
|
val array = LongArray(length)
|
|
|
|
if (optional(length shl 3) == length shl 3) {
|
2023-01-24 20:37:56 +01:00
|
|
|
val byteBuf = byteBuf
|
2021-08-20 03:53:48 +02:00
|
|
|
for (i in 0 until length) {
|
|
|
|
array[i] = byteBuf.readLong()
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
2021-08-20 03:53:48 +02:00
|
|
|
position = byteBuf.readerIndex()
|
2021-08-20 03:09:33 +02:00
|
|
|
} else {
|
2021-08-20 03:53:48 +02:00
|
|
|
for (i in 0 until length) array[i] = readLong()
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
2021-08-20 03:53:48 +02:00
|
|
|
return array
|
|
|
|
}
|
|
|
|
|
|
|
|
@Throws(KryoException::class)
|
|
|
|
override fun readFloats(length: Int): FloatArray {
|
|
|
|
val array = FloatArray(length)
|
|
|
|
if (optional(length shl 2) == length shl 2) {
|
2023-01-24 20:37:56 +01:00
|
|
|
val byteBuf = byteBuf
|
2021-08-20 03:53:48 +02:00
|
|
|
for (i in 0 until length) {
|
|
|
|
array[i] = byteBuf.readFloat()
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
2021-08-20 03:53:48 +02:00
|
|
|
position = byteBuf.readerIndex()
|
2021-08-20 03:09:33 +02:00
|
|
|
} else {
|
2021-08-20 03:53:48 +02:00
|
|
|
for (i in 0 until length) array[i] = readFloat()
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
2021-08-20 03:53:48 +02:00
|
|
|
return array
|
|
|
|
}
|
|
|
|
|
|
|
|
@Throws(KryoException::class)
|
|
|
|
override fun readDoubles(length: Int): DoubleArray {
|
|
|
|
val array = DoubleArray(length)
|
|
|
|
if (optional(length shl 3) == length shl 3) {
|
2023-01-24 20:37:56 +01:00
|
|
|
val byteBuf = byteBuf
|
2021-08-20 03:53:48 +02:00
|
|
|
for (i in 0 until length) {
|
|
|
|
array[i] = byteBuf.readDouble()
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
2021-08-20 03:53:48 +02:00
|
|
|
position = byteBuf.readerIndex()
|
2021-08-20 03:09:33 +02:00
|
|
|
} else {
|
2021-08-20 03:53:48 +02:00
|
|
|
for (i in 0 until length) array[i] = readDouble()
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
2021-08-20 03:53:48 +02:00
|
|
|
return array
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
|
2021-08-20 03:53:48 +02:00
|
|
|
@Throws(KryoException::class)
|
|
|
|
override fun readShorts(length: Int): ShortArray {
|
|
|
|
val array = ShortArray(length)
|
|
|
|
if (optional(length shl 1) == length shl 1) {
|
|
|
|
val byteBuf = byteBuf
|
2023-01-24 20:37:56 +01:00
|
|
|
for (i in 0 until length) array[i] = (byteBuf.readByte().toInt() and 0xFF or (byteBuf.readByte().toInt() and 0xFF shl 8)).toShort()
|
|
|
|
position = byteBuf.readerIndex()
|
2021-08-20 03:09:33 +02:00
|
|
|
} else {
|
2021-08-20 03:53:48 +02:00
|
|
|
for (i in 0 until length) array[i] = readShort()
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
2021-08-20 03:53:48 +02:00
|
|
|
return array
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
|
2021-08-20 03:53:48 +02:00
|
|
|
@Throws(KryoException::class)
|
|
|
|
override fun readChars(length: Int): CharArray {
|
|
|
|
val array = CharArray(length)
|
|
|
|
if (optional(length shl 1) == length shl 1) {
|
|
|
|
val byteBuf = byteBuf
|
2023-01-24 20:37:56 +01:00
|
|
|
for (i in 0 until length) array[i] = (byteBuf.readByte().toInt() and 0xFF or (byteBuf.readByte().toInt() and 0xFF shl 8)).toChar()
|
|
|
|
position = byteBuf.readerIndex()
|
2021-08-20 03:09:33 +02:00
|
|
|
} else {
|
2021-08-20 03:53:48 +02:00
|
|
|
for (i in 0 until length) array[i] = readChar()
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
2021-08-20 03:53:48 +02:00
|
|
|
return array
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
|
2021-08-20 03:53:48 +02:00
|
|
|
@Throws(KryoException::class)
|
|
|
|
override fun readBooleans(length: Int): BooleanArray {
|
|
|
|
val array = BooleanArray(length)
|
2021-08-20 03:09:33 +02:00
|
|
|
if (optional(length) == length) {
|
2021-08-20 03:53:48 +02:00
|
|
|
val byteBuf = byteBuf
|
2023-01-24 20:37:56 +01:00
|
|
|
for (i in 0 until length) array[i] = byteBuf.readByte().toInt() != 0
|
|
|
|
position = byteBuf.readerIndex()
|
2021-08-20 03:09:33 +02:00
|
|
|
} else {
|
2021-08-20 03:53:48 +02:00
|
|
|
for (i in 0 until length) array[i] = readBoolean()
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
2021-08-20 03:53:48 +02:00
|
|
|
return array
|
2021-08-20 03:09:33 +02:00
|
|
|
}
|
|
|
|
}
|