optimize utils converted to kotlin

This commit is contained in:
Robinson 2023-01-25 01:35:53 +01:00
parent cef8cb7f5c
commit d278130ea2
No known key found for this signature in database
GPG Key ID: 8E7DB78588BD6F5C
4 changed files with 792 additions and 858 deletions

View File

@ -1,477 +0,0 @@
/*
* Copyright 2021 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.bytes;
@SuppressWarnings({"Duplicates", "NumericCastThatLosesPrecision", "UnusedAssignment", "unused"})
public
class OptimizeUtilsByteArray {
/**
* Returns the number of bytes that would be written with {@link #writeInt(byte[], int, boolean)}.
*
* @param optimizePositive
* true if you want to optimize the number of bytes needed to write the length value
*/
public static
int intLength(int value, boolean optimizePositive) {
return dorkbox.bytes.OptimizeUtilsByteBuf.intLength(value, optimizePositive);
}
// int
/**
* look at buffer, and see if we can read the length of the int off of it. (from the reader index)
*
* @return 0 if we could not read anything, >0 for the number of bytes for the int on the buffer
*/
@SuppressWarnings("SimplifiableIfStatement")
public static
boolean canReadInt(byte[] buffer) {
int position = 0;
return canReadInt(buffer, position);
}
/**
* FROM KRYO
* <p>
* look at buffer, and see if we can read the length of the int off of it. (from the reader index)
*
* @param position where in the buffer to start reading
* @return 0 if we could not read anything, >0 for the number of bytes for the int on the buffer
*/
@SuppressWarnings("SimplifiableIfStatement")
public static
boolean canReadInt(final byte[] buffer, int position) {
int length = buffer.length;
if (length >= 5) {
return true;
}
if ((buffer[position++] & 0x80) == 0) {
return true;
}
if (position == length) {
return false;
}
if ((buffer[position++] & 0x80) == 0) {
return true;
}
if (position == length) {
return false;
}
if ((buffer[position++] & 0x80) == 0) {
return true;
}
if (position == length) {
return false;
}
if ((buffer[position++] & 0x80) == 0) {
return true;
}
return position != length;
}
/**
* Reads an int from the buffer that was optimized at position 0
*
* @param optimizePositive
* If true, small positive numbers will be more efficient (1 byte) and small negative numbers will be inefficient (5
* bytes). This ultimately means that it will use fewer bytes for positive numbers.
*/
public static
int readInt(byte[] buffer, boolean optimizePositive) {
int position = 0;
return readInt(buffer, optimizePositive, position);
}
/**
* FROM KRYO
* <p>
* Reads an int from the buffer that was optimized.
*
* @param position where in the buffer to start reading
* @param optimizePositive
* If true, small positive numbers will be more efficient (1 byte) and small negative numbers will be inefficient (5
* bytes). This ultimately means that it will use fewer bytes for positive numbers.
*/
public static
int readInt(final byte[] buffer, final boolean optimizePositive, int position) {
int b = buffer[position++];
int result = b & 0x7F;
if ((b & 0x80) != 0) {
b = buffer[position++];
result |= (b & 0x7F) << 7;
if ((b & 0x80) != 0) {
b = buffer[position++];
result |= (b & 0x7F) << 14;
if ((b & 0x80) != 0) {
b = buffer[position++];
result |= (b & 0x7F) << 21;
if ((b & 0x80) != 0) {
b = buffer[position++];
result |= (b & 0x7F) << 28;
}
}
}
}
return optimizePositive ? result : result >>> 1 ^ -(result & 1);
}
/**
* Writes the specified int to the buffer using 1 to 5 bytes, depending on the size of the number.
*
* @param optimizePositive
* If true, small positive numbers will be more efficient (1 byte) and small negative numbers will be inefficient (5
* bytes). This ultimately means that it will use fewer bytes for positive numbers.
*
* @return the number of bytes written.
*/
public static
int writeInt(byte[] buffer, int value, boolean optimizePositive) {
int position = 0;
return writeInt(buffer, value, optimizePositive, position);
}
/**
* FROM KRYO
* <p>
* Writes the specified int to the buffer using 1 to 5 bytes, depending on the size of the number.
*
* @param position where in the buffer to start writing
* @param optimizePositive
* If true, small positive numbers will be more efficient (1 byte) and small negative numbers will be inefficient (5
* bytes). This ultimately means that it will use fewer bytes for positive numbers.
*
* @return the number of bytes written.
*/
public static
int writeInt(final byte[] buffer, int value, final boolean optimizePositive, int position) {
if (!optimizePositive) {
value = value << 1 ^ value >> 31;
}
if (value >>> 7 == 0) {
buffer[position++] = (byte) value;
return 1;
}
if (value >>> 14 == 0) {
buffer[position++] = (byte) (value & 0x7F | 0x80);
buffer[position++] = (byte) (value >>> 7);
return 2;
}
if (value >>> 21 == 0) {
buffer[position++] = (byte) (value & 0x7F | 0x80);
buffer[position++] = (byte) (value >>> 7 | 0x80);
buffer[position++] = (byte) (value >>> 14);
return 3;
}
if (value >>> 28 == 0) {
buffer[position++] = (byte) (value & 0x7F | 0x80);
buffer[position++] = (byte) (value >>> 7 | 0x80);
buffer[position++] = (byte) (value >>> 14 | 0x80);
buffer[position++] = (byte) (value >>> 21);
return 4;
}
buffer[position++] = (byte) (value & 0x7F | 0x80);
buffer[position++] = (byte) (value >>> 7 | 0x80);
buffer[position++] = (byte) (value >>> 14 | 0x80);
buffer[position++] = (byte) (value >>> 21 | 0x80);
buffer[position++] = (byte) (value >>> 28);
return 5;
}
/**
* Returns 1-9 bytes that would be written with {@link #writeLong(byte[], long, boolean)}.
*
* @param optimizePositive
* If true, small positive numbers will be more efficient (1 byte) and small negative numbers will be inefficient (9
* bytes). This ultimately means that it will use fewer bytes for positive numbers.
*/
public static
int longLength(long value, boolean optimizePositive) {
return dorkbox.bytes.OptimizeUtilsByteBuf.longLength(value, optimizePositive);
}
// long
/**
* Reads a 1-9 byte long.
*
* @param optimizePositive
* If true, small positive numbers will be more efficient (1 byte) and small negative numbers will be inefficient (9
* bytes). This ultimately means that it will use fewer bytes for positive numbers.
*/
public static
long readLong(byte[] buffer, boolean optimizePositive) {
int position = 0;
return readLong(buffer, optimizePositive, position);
}
/**
* FROM KRYO
* <p>
* Reads a 1-9 byte long.
*
* @param position where in the buffer to start reading
* @param optimizePositive
* If true, small positive numbers will be more efficient (1 byte) and small negative numbers will be inefficient (9
* bytes). This ultimately means that it will use fewer bytes for positive numbers.
*/
public static
long readLong(final byte[] buffer, final boolean optimizePositive, int position) {
int b = buffer[position++];
long result = b & 0x7F;
if ((b & 0x80) != 0) {
b = buffer[position++];
result |= (b & 0x7F) << 7;
if ((b & 0x80) != 0) {
b = buffer[position++];
result |= (b & 0x7F) << 14;
if ((b & 0x80) != 0) {
b = buffer[position++];
result |= (b & 0x7F) << 21;
if ((b & 0x80) != 0) {
b = buffer[position++];
result |= (long) (b & 0x7F) << 28;
if ((b & 0x80) != 0) {
b = buffer[position++];
result |= (long) (b & 0x7F) << 35;
if ((b & 0x80) != 0) {
b = buffer[position++];
result |= (long) (b & 0x7F) << 42;
if ((b & 0x80) != 0) {
b = buffer[position++];
result |= (long) (b & 0x7F) << 49;
if ((b & 0x80) != 0) {
b = buffer[position++];
result |= (long) b << 56;
}
}
}
}
}
}
}
}
if (!optimizePositive) {
result = result >>> 1 ^ -(result & 1);
}
return result;
}
/**
* Writes a 1-9 byte long.
*
* @param optimizePositive
* If true, small positive numbers will be more efficient (1 byte) and small negative numbers will be inefficient (9
* bytes).
*
* @return the number of bytes written.
*/
public static
int writeLong(byte[] buffer, long value, boolean optimizePositive) {
int position = 0;
return writeLong(buffer, value, optimizePositive, position);
}
/**
* FROM KRYO
* <p>
* Writes a 1-9 byte long.
*
* @param position where in the buffer to start writing
* @param optimizePositive
* If true, small positive numbers will be more efficient (1 byte) and small negative numbers will be inefficient (9
* bytes).
*
* @return the number of bytes written.
*/
public static
int writeLong(final byte[] buffer, long value, final boolean optimizePositive, int position) {
if (!optimizePositive) {
value = value << 1 ^ value >> 63;
}
if (value >>> 7 == 0) {
buffer[position++] = (byte) value;
return 1;
}
if (value >>> 14 == 0) {
buffer[position++] = (byte) (value & 0x7F | 0x80);
buffer[position++] = (byte) (value >>> 7);
return 2;
}
if (value >>> 21 == 0) {
buffer[position++] = (byte) (value & 0x7F | 0x80);
buffer[position++] = (byte) (value >>> 7 | 0x80);
buffer[position++] = (byte) (value >>> 14);
return 3;
}
if (value >>> 28 == 0) {
buffer[position++] = (byte) (value & 0x7F | 0x80);
buffer[position++] = (byte) (value >>> 7 | 0x80);
buffer[position++] = (byte) (value >>> 14 | 0x80);
buffer[position++] = (byte) (value >>> 21);
return 4;
}
if (value >>> 35 == 0) {
buffer[position++] = (byte) (value & 0x7F | 0x80);
buffer[position++] = (byte) (value >>> 7 | 0x80);
buffer[position++] = (byte) (value >>> 14 | 0x80);
buffer[position++] = (byte) (value >>> 21 | 0x80);
buffer[position++] = (byte) (value >>> 28);
return 5;
}
if (value >>> 42 == 0) {
buffer[position++] = (byte) (value & 0x7F | 0x80);
buffer[position++] = (byte) (value >>> 7 | 0x80);
buffer[position++] = (byte) (value >>> 14 | 0x80);
buffer[position++] = (byte) (value >>> 21 | 0x80);
buffer[position++] = (byte) (value >>> 28 | 0x80);
buffer[position++] = (byte) (value >>> 35);
return 6;
}
if (value >>> 49 == 0) {
buffer[position++] = (byte) (value & 0x7F | 0x80);
buffer[position++] = (byte) (value >>> 7 | 0x80);
buffer[position++] = (byte) (value >>> 14 | 0x80);
buffer[position++] = (byte) (value >>> 21 | 0x80);
buffer[position++] = (byte) (value >>> 28 | 0x80);
buffer[position++] = (byte) (value >>> 35 | 0x80);
buffer[position++] = (byte) (value >>> 42);
return 7;
}
if (value >>> 56 == 0) {
buffer[position++] = (byte) (value & 0x7F | 0x80);
buffer[position++] = (byte) (value >>> 7 | 0x80);
buffer[position++] = (byte) (value >>> 14 | 0x80);
buffer[position++] = (byte) (value >>> 21 | 0x80);
buffer[position++] = (byte) (value >>> 28 | 0x80);
buffer[position++] = (byte) (value >>> 35 | 0x80);
buffer[position++] = (byte) (value >>> 42 | 0x80);
buffer[position++] = (byte) (value >>> 49);
return 8;
}
buffer[position++] = (byte) (value & 0x7F | 0x80);
buffer[position++] = (byte) (value >>> 7 | 0x80);
buffer[position++] = (byte) (value >>> 14 | 0x80);
buffer[position++] = (byte) (value >>> 21 | 0x80);
buffer[position++] = (byte) (value >>> 28 | 0x80);
buffer[position++] = (byte) (value >>> 35 | 0x80);
buffer[position++] = (byte) (value >>> 42 | 0x80);
buffer[position++] = (byte) (value >>> 49 | 0x80);
buffer[position++] = (byte) (value >>> 56);
return 9;
}
/**
* look at buffer, and see if we can read the length of the long off of it (from the reader index).
*
* @return 0 if we could not read anything, >0 for the number of bytes for the long on the buffer
*/
public static
boolean canReadLong(byte[] buffer) {
int position = 0;
return canReadLong(buffer, position);
}
/**
* FROM KRYO
* <p>
* look at buffer, and see if we can read the length of the long off of it (from the reader index).
*
* @param position where in the buffer to start reading
* @return 0 if we could not read anything, >0 for the number of bytes for the long on the buffer
*/
private static
boolean canReadLong(final byte[] buffer, int position) {
int limit = buffer.length;
if (limit >= 9) {
return true;
}
if ((buffer[position++] & 0x80) == 0) {
return true;
}
if (position == limit) {
return false;
}
if ((buffer[position++] & 0x80) == 0) {
return true;
}
if (position == limit) {
return false;
}
if ((buffer[position++] & 0x80) == 0) {
return true;
}
if (position == limit) {
return false;
}
if ((buffer[position++] & 0x80) == 0) {
return true;
}
if (position == limit) {
return false;
}
if ((buffer[position++] & 0x80) == 0) {
return true;
}
if (position == limit) {
return false;
}
if ((buffer[position++] & 0x80) == 0) {
return true;
}
if (position == limit) {
return false;
}
if ((buffer[position++] & 0x80) == 0) {
return true;
}
if (position == limit) {
return false;
}
//noinspection SimplifiableIfStatement
if ((buffer[position++] & 0x80) == 0) {
return true;
}
return position != limit;
}
private
OptimizeUtilsByteArray() {
}
}

View File

@ -0,0 +1,395 @@
/*
* Copyright 2023 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.
*/
@file:Suppress("UNUSED_CHANGED_VALUE", "NAME_SHADOWING")
package dorkbox.bytes
@Suppress("unused")
object OptimizeUtilsByteArray {
/**
* Returns the number of bytes that would be written with [.writeInt].
*
* @param optimizePositive
* true if you want to optimize the number of bytes needed to write the length value
*/
fun intLength(value: Int, optimizePositive: Boolean): Int {
return OptimizeUtilsByteBuf.intLength(value, optimizePositive)
}
/**
* FROM KRYO
*
*
* look at buffer, and see if we can read the length of the int off of it. (from the reader index)
*
* @param position where in the buffer to start reading
* @return 0 if we could not read anything, >0 for the number of bytes for the int on the buffer
*/
fun canReadInt(buffer: ByteArray, position: Int = 0): Boolean {
var position = position
val length = buffer.size
if (length >= 5) {
return true
}
if (position + 1 > length) {
return false
}
if (buffer[position++].toInt() and 0x80 == 0) {
return true
}
if (position == length) {
return false
}
if (buffer[position++].toInt() and 0x80 == 0) {
return true
}
if (position == length) {
return false
}
if (buffer[position++].toInt() and 0x80 == 0) {
return true
}
if (position == length) {
return false
}
return if (buffer[position++].toInt() and 0x80 == 0) {
true
} else position != length
}
/**
* FROM KRYO
*
*
* Reads an int from the buffer that was optimized.
*
* @param position where in the buffer to start reading
*/
fun readInt(buffer: ByteArray, position: Int): Int {
return readInt(buffer, false, position)
}
/**
* FROM KRYO
*
*
* Reads an int from the buffer that was optimized.
*
* @param position where in the buffer to start reading
* @param optimizePositive
* If true, small positive numbers will be more efficient (1 byte) and small negative numbers will be inefficient (5
* bytes). This ultimately means that it will use fewer bytes for positive numbers.
*/
fun readInt(buffer: ByteArray, optimizePositive: Boolean = false, position: Int = 0): Int {
var position = position
var b = buffer[position++].toInt()
var result = b and 0x7F
if (b and 0x80 != 0) {
b = buffer[position++].toInt()
result = result or (b and 0x7F shl 7)
if (b and 0x80 != 0) {
b = buffer[position++].toInt()
result = result or (b and 0x7F shl 14)
if (b and 0x80 != 0) {
b = buffer[position++].toInt()
result = result or (b and 0x7F shl 21)
if (b and 0x80 != 0) {
b = buffer[position++].toInt()
result = result or (b and 0x7F shl 28)
}
}
}
}
return if (optimizePositive) result else result ushr 1 xor -(result and 1)
}
/**
* FROM KRYO
*
*
* Writes the specified int to the buffer using 1 to 5 bytes, depending on the size of the number.
*
* @param position where in the buffer to start writing
* @param optimizePositive
* If true, small positive numbers will be more efficient (1 byte) and small negative numbers will be inefficient (5
* bytes). This ultimately means that it will use fewer bytes for positive numbers.
*
* @return the number of bytes written.
*/
fun writeInt(buffer: ByteArray, value: Int, optimizePositive: Boolean = false, position: Int = 0): Int {
var value = value
var position = position
if (!optimizePositive) {
value = value shl 1 xor (value shr 31)
}
if (value ushr 7 == 0) {
buffer[position++] = value.toByte()
return 1
}
if (value ushr 14 == 0) {
buffer[position++] = (value and 0x7F or 0x80).toByte()
buffer[position++] = (value ushr 7).toByte()
return 2
}
if (value ushr 21 == 0) {
buffer[position++] = (value and 0x7F or 0x80).toByte()
buffer[position++] = (value ushr 7 or 0x80).toByte()
buffer[position++] = (value ushr 14).toByte()
return 3
}
if (value ushr 28 == 0) {
buffer[position++] = (value and 0x7F or 0x80).toByte()
buffer[position++] = (value ushr 7 or 0x80).toByte()
buffer[position++] = (value ushr 14 or 0x80).toByte()
buffer[position++] = (value ushr 21).toByte()
return 4
}
buffer[position++] = (value and 0x7F or 0x80).toByte()
buffer[position++] = (value ushr 7 or 0x80).toByte()
buffer[position++] = (value ushr 14 or 0x80).toByte()
buffer[position++] = (value ushr 21 or 0x80).toByte()
buffer[position++] = (value ushr 28).toByte()
return 5
}
/**
* Returns 1-9 bytes that would be written with [.writeLong].
*
* @param optimizePositive
* If true, small positive numbers will be more efficient (1 byte) and small negative numbers will be inefficient (9
* bytes). This ultimately means that it will use fewer bytes for positive numbers.
*/
fun longLength(value: Long, optimizePositive: Boolean): Int {
return OptimizeUtilsByteBuf.longLength(value, optimizePositive)
}
// long
/**
* FROM KRYO
*
*
* Reads a 1-9 byte long.
*
* @param position where in the buffer to start reading
* @param optimizePositive
* If true, small positive numbers will be more efficient (1 byte) and small negative numbers will be inefficient (9
* bytes). This ultimately means that it will use fewer bytes for positive numbers.
*/
fun readLong(buffer: ByteArray, optimizePositive: Boolean = false, position: Int = 0): Long {
var position = position
var b = buffer[position++].toInt()
var result = (b and 0x7F).toLong()
if (b and 0x80 != 0) {
b = buffer[position++].toInt()
result = result or (b and 0x7F shl 7).toLong()
if (b and 0x80 != 0) {
b = buffer[position++].toInt()
result = result or (b and 0x7F shl 14).toLong()
if (b and 0x80 != 0) {
b = buffer[position++].toInt()
result = result or (b and 0x7F shl 21).toLong()
if (b and 0x80 != 0) {
b = buffer[position++].toInt()
result = result or ((b and 0x7F).toLong() shl 28)
if (b and 0x80 != 0) {
b = buffer[position++].toInt()
result = result or ((b and 0x7F).toLong() shl 35)
if (b and 0x80 != 0) {
b = buffer[position++].toInt()
result = result or ((b and 0x7F).toLong() shl 42)
if (b and 0x80 != 0) {
b = buffer[position++].toInt()
result = result or ((b and 0x7F).toLong() shl 49)
if (b and 0x80 != 0) {
b = buffer[position++].toInt()
result = result or (b.toLong() shl 56)
}
}
}
}
}
}
}
}
if (!optimizePositive) {
result = result ushr 1 xor -(result and 1L)
}
return result
}
/**
* FROM KRYO
*
*
* Writes a 1-9 byte long.
*
* @param position where in the buffer to start writing
* @param optimizePositive
* If true, small positive numbers will be more efficient (1 byte) and small negative numbers will be inefficient (9
* bytes).
*
* @return the number of bytes written.
*/
fun writeLong(buffer: ByteArray, value: Long, optimizePositive: Boolean = false, position: Int = 0): Int {
var value = value
var position = position
if (!optimizePositive) {
value = value shl 1 xor (value shr 63)
}
if (value ushr 7 == 0L) {
buffer[position++] = value.toByte()
return 1
}
if (value ushr 14 == 0L) {
buffer[position++] = (value and 0x7FL or 0x80L).toByte()
buffer[position++] = (value ushr 7).toByte()
return 2
}
if (value ushr 21 == 0L) {
buffer[position++] = (value and 0x7FL or 0x80L).toByte()
buffer[position++] = (value ushr 7 or 0x80L).toByte()
buffer[position++] = (value ushr 14).toByte()
return 3
}
if (value ushr 28 == 0L) {
buffer[position++] = (value and 0x7FL or 0x80L).toByte()
buffer[position++] = (value ushr 7 or 0x80L).toByte()
buffer[position++] = (value ushr 14 or 0x80L).toByte()
buffer[position++] = (value ushr 21).toByte()
return 4
}
if (value ushr 35 == 0L) {
buffer[position++] = (value and 0x7FL or 0x80L).toByte()
buffer[position++] = (value ushr 7 or 0x80L).toByte()
buffer[position++] = (value ushr 14 or 0x80L).toByte()
buffer[position++] = (value ushr 21 or 0x80L).toByte()
buffer[position++] = (value ushr 28).toByte()
return 5
}
if (value ushr 42 == 0L) {
buffer[position++] = (value and 0x7FL or 0x80L).toByte()
buffer[position++] = (value ushr 7 or 0x80L).toByte()
buffer[position++] = (value ushr 14 or 0x80L).toByte()
buffer[position++] = (value ushr 21 or 0x80L).toByte()
buffer[position++] = (value ushr 28 or 0x80L).toByte()
buffer[position++] = (value ushr 35).toByte()
return 6
}
if (value ushr 49 == 0L) {
buffer[position++] = (value and 0x7FL or 0x80L).toByte()
buffer[position++] = (value ushr 7 or 0x80L).toByte()
buffer[position++] = (value ushr 14 or 0x80L).toByte()
buffer[position++] = (value ushr 21 or 0x80L).toByte()
buffer[position++] = (value ushr 28 or 0x80L).toByte()
buffer[position++] = (value ushr 35 or 0x80L).toByte()
buffer[position++] = (value ushr 42).toByte()
return 7
}
if (value ushr 56 == 0L) {
buffer[position++] = (value and 0x7FL or 0x80L).toByte()
buffer[position++] = (value ushr 7 or 0x80L).toByte()
buffer[position++] = (value ushr 14 or 0x80L).toByte()
buffer[position++] = (value ushr 21 or 0x80L).toByte()
buffer[position++] = (value ushr 28 or 0x80L).toByte()
buffer[position++] = (value ushr 35 or 0x80L).toByte()
buffer[position++] = (value ushr 42 or 0x80L).toByte()
buffer[position++] = (value ushr 49).toByte()
return 8
}
buffer[position++] = (value and 0x7FL or 0x80L).toByte()
buffer[position++] = (value ushr 7 or 0x80L).toByte()
buffer[position++] = (value ushr 14 or 0x80L).toByte()
buffer[position++] = (value ushr 21 or 0x80L).toByte()
buffer[position++] = (value ushr 28 or 0x80L).toByte()
buffer[position++] = (value ushr 35 or 0x80L).toByte()
buffer[position++] = (value ushr 42 or 0x80L).toByte()
buffer[position++] = (value ushr 49 or 0x80L).toByte()
buffer[position++] = (value ushr 56).toByte()
return 9
}
/**
* look at buffer, and see if we can read the length of the long off of it (from the reader index).
*
* @return 0 if we could not read anything, >0 for the number of bytes for the long on the buffer
*/
fun canReadLong(buffer: ByteArray): Boolean {
val position = 0
return canReadLong(buffer, position)
}
/**
* FROM KRYO
*
*
* look at buffer, and see if we can read the length of the long off of it (from the reader index).
*
* @param position where in the buffer to start reading
* @return 0 if we could not read anything, >0 for the number of bytes for the long on the buffer
*/
private fun canReadLong(buffer: ByteArray, position: Int): Boolean {
var position = position
val limit = buffer.size
if (limit >= 9) {
return true
}
if (buffer[position++].toInt() and 0x80 == 0) {
return true
}
if (position == limit) {
return false
}
if (buffer[position++].toInt() and 0x80 == 0) {
return true
}
if (position == limit) {
return false
}
if (buffer[position++].toInt() and 0x80 == 0) {
return true
}
if (position == limit) {
return false
}
if (buffer[position++].toInt() and 0x80 == 0) {
return true
}
if (position == limit) {
return false
}
if (buffer[position++].toInt() and 0x80 == 0) {
return true
}
if (position == limit) {
return false
}
if (buffer[position++].toInt() and 0x80 == 0) {
return true
}
if (position == limit) {
return false
}
if (buffer[position++].toInt() and 0x80 == 0) {
return true
}
if (position == limit) {
return false
}
return if (buffer[position++].toInt() and 0x80 == 0) {
true
} else position != limit
}
}

View File

@ -1,381 +0,0 @@
/*
* Copyright 2021 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.bytes;
import io.netty.buffer.ByteBuf;
@SuppressWarnings({"Duplicates", "NumericCastThatLosesPrecision", "unused"})
public
class OptimizeUtilsByteBuf {
// int
/**
* FROM KRYO
* <p>
* Returns the number of bytes that would be written with {@link #writeInt(ByteBuf, int, boolean)}.
*
* @param optimizePositive
* If true, small positive numbers will be more efficient (1 byte) and small negative numbers will be inefficient (5
* bytes). This ultimately means that it will use fewer bytes for positive numbers.
*/
public static
int intLength(int value, boolean optimizePositive) {
if (!optimizePositive) {
value = value << 1 ^ value >> 31;
}
if (value >>> 7 == 0) {
return 1;
}
if (value >>> 14 == 0) {
return 2;
}
if (value >>> 21 == 0) {
return 3;
}
if (value >>> 28 == 0) {
return 4;
}
return 5;
}
/**
* FROM KRYO
* <p>
* look at buffer, and see if we can read the length of the int off of it. (from the reader index)
*
* @return 0 if we could not read anything, >0 for the number of bytes for the int on the buffer
*/
public static
int canReadInt(ByteBuf buffer) {
int startIndex = buffer.readerIndex();
try {
int remaining = buffer.readableBytes();
for (int offset = 0, count = 1; offset < 32 && remaining > 0; offset += 7, remaining--, count++) {
int b = buffer.readByte();
if ((b & 0x80) == 0) {
return count;
}
}
return 0;
} finally {
buffer.readerIndex(startIndex);
}
}
/**
* FROM KRYO
* <p>
* Reads an int from the buffer that was optimized.
*
* @param optimizePositive
* If true, small positive numbers will be more efficient (1 byte) and small negative numbers will be inefficient (5
* bytes). This ultimately means that it will use fewer bytes for positive numbers.
*
* @return the number of bytes written.
*/
public static
int readInt(ByteBuf buffer, boolean optimizePositive) {
int b = buffer.readByte();
int result = b & 0x7F;
if ((b & 0x80) != 0) {
b = buffer.readByte();
result |= (b & 0x7F) << 7;
if ((b & 0x80) != 0) {
b = buffer.readByte();
result |= (b & 0x7F) << 14;
if ((b & 0x80) != 0) {
b = buffer.readByte();
result |= (b & 0x7F) << 21;
if ((b & 0x80) != 0) {
b = buffer.readByte();
result |= (b & 0x7F) << 28;
}
}
}
}
return optimizePositive ? result : result >>> 1 ^ -(result & 1);
}
/**
* FROM KRYO
* <p>
* Writes the specified int to the buffer using 1 to 5 bytes, depending on the size of the number.
*
* @param optimizePositive
* If true, small positive numbers will be more efficient (1 byte) and small negative numbers will be inefficient (5
* bytes). This ultimately means that it will use fewer bytes for positive numbers.
*
* @return the number of bytes written.
*/
public static
int writeInt(ByteBuf buffer, int value, boolean optimizePositive) {
if (!optimizePositive) {
value = value << 1 ^ value >> 31;
}
if (value >>> 7 == 0) {
buffer.writeByte((byte) value);
return 1;
}
if (value >>> 14 == 0) {
buffer.writeByte((byte) (value & 0x7F | 0x80));
buffer.writeByte((byte) (value >>> 7));
return 2;
}
if (value >>> 21 == 0) {
buffer.writeByte((byte) (value & 0x7F | 0x80));
buffer.writeByte((byte) (value >>> 7 | 0x80));
buffer.writeByte((byte) (value >>> 14));
return 3;
}
if (value >>> 28 == 0) {
buffer.writeByte((byte) (value & 0x7F | 0x80));
buffer.writeByte((byte) (value >>> 7 | 0x80));
buffer.writeByte((byte) (value >>> 14 | 0x80));
buffer.writeByte((byte) (value >>> 21));
return 4;
}
buffer.writeByte((byte) (value & 0x7F | 0x80));
buffer.writeByte((byte) (value >>> 7 | 0x80));
buffer.writeByte((byte) (value >>> 14 | 0x80));
buffer.writeByte((byte) (value >>> 21 | 0x80));
buffer.writeByte((byte) (value >>> 28));
return 5;
}
// long
/**
* Returns the 1-9 bytes that would be written with {@link #writeLong(ByteBuf, long, boolean)}.
*
* @param optimizePositive
* If true, small positive numbers will be more efficient (1 byte) and small negative numbers will be inefficient (9
* bytes). This ultimately means that it will use fewer bytes for positive numbers.
*/
public static
int longLength(long value, boolean optimizePositive) {
if (!optimizePositive) {
value = value << 1 ^ value >> 63;
}
if (value >>> 7 == 0) {
return 1;
}
if (value >>> 14 == 0) {
return 2;
}
if (value >>> 21 == 0) {
return 3;
}
if (value >>> 28 == 0) {
return 4;
}
if (value >>> 35 == 0) {
return 5;
}
if (value >>> 42 == 0) {
return 6;
}
if (value >>> 49 == 0) {
return 7;
}
if (value >>> 56 == 0) {
return 8;
}
return 9;
}
/**
* FROM KRYO
* <p>
* Reads a 1-9 byte long.
*
* @param optimizePositive
* If true, small positive numbers will be more efficient (1 byte) and small negative numbers will be inefficient (9
* bytes). This ultimately means that it will use fewer bytes for positive numbers.
*/
public static
long readLong(ByteBuf buffer, boolean optimizePositive) {
int b = buffer.readByte();
long result = b & 0x7F;
if ((b & 0x80) != 0) {
b = buffer.readByte();
result |= (b & 0x7F) << 7;
if ((b & 0x80) != 0) {
b = buffer.readByte();
result |= (b & 0x7F) << 14;
if ((b & 0x80) != 0) {
b = buffer.readByte();
result |= (b & 0x7F) << 21;
if ((b & 0x80) != 0) {
b = buffer.readByte();
result |= (long) (b & 0x7F) << 28;
if ((b & 0x80) != 0) {
b = buffer.readByte();
result |= (long) (b & 0x7F) << 35;
if ((b & 0x80) != 0) {
b = buffer.readByte();
result |= (long) (b & 0x7F) << 42;
if ((b & 0x80) != 0) {
b = buffer.readByte();
result |= (long) (b & 0x7F) << 49;
if ((b & 0x80) != 0) {
b = buffer.readByte();
result |= (long) b << 56;
}
}
}
}
}
}
}
}
if (!optimizePositive) {
result = result >>> 1 ^ -(result & 1);
}
return result;
}
/**
* FROM KRYO
* <p>
* Writes a 1-9 byte long.
*
* @param optimizePositive
* If true, small positive numbers will be more efficient (1 byte) and small negative numbers will be inefficient (9
* bytes). This ultimately means that it will use fewer bytes for positive numbers.
*
* @return the number of bytes written.
*/
public static
int writeLong(ByteBuf buffer, long value, boolean optimizePositive) {
if (!optimizePositive) {
value = value << 1 ^ value >> 63;
}
if (value >>> 7 == 0) {
buffer.writeByte((byte) value);
return 1;
}
if (value >>> 14 == 0) {
buffer.writeByte((byte) (value & 0x7F | 0x80));
buffer.writeByte((byte) (value >>> 7));
return 2;
}
if (value >>> 21 == 0) {
buffer.writeByte((byte) (value & 0x7F | 0x80));
buffer.writeByte((byte) (value >>> 7 | 0x80));
buffer.writeByte((byte) (value >>> 14));
return 3;
}
if (value >>> 28 == 0) {
buffer.writeByte((byte) (value & 0x7F | 0x80));
buffer.writeByte((byte) (value >>> 7 | 0x80));
buffer.writeByte((byte) (value >>> 14 | 0x80));
buffer.writeByte((byte) (value >>> 21));
return 4;
}
if (value >>> 35 == 0) {
buffer.writeByte((byte) (value & 0x7F | 0x80));
buffer.writeByte((byte) (value >>> 7 | 0x80));
buffer.writeByte((byte) (value >>> 14 | 0x80));
buffer.writeByte((byte) (value >>> 21 | 0x80));
buffer.writeByte((byte) (value >>> 28));
return 5;
}
if (value >>> 42 == 0) {
buffer.writeByte((byte) (value & 0x7F | 0x80));
buffer.writeByte((byte) (value >>> 7 | 0x80));
buffer.writeByte((byte) (value >>> 14 | 0x80));
buffer.writeByte((byte) (value >>> 21 | 0x80));
buffer.writeByte((byte) (value >>> 28 | 0x80));
buffer.writeByte((byte) (value >>> 35));
return 6;
}
if (value >>> 49 == 0) {
buffer.writeByte((byte) (value & 0x7F | 0x80));
buffer.writeByte((byte) (value >>> 7 | 0x80));
buffer.writeByte((byte) (value >>> 14 | 0x80));
buffer.writeByte((byte) (value >>> 21 | 0x80));
buffer.writeByte((byte) (value >>> 28 | 0x80));
buffer.writeByte((byte) (value >>> 35 | 0x80));
buffer.writeByte((byte) (value >>> 42));
return 7;
}
if (value >>> 56 == 0) {
buffer.writeByte((byte) (value & 0x7F | 0x80));
buffer.writeByte((byte) (value >>> 7 | 0x80));
buffer.writeByte((byte) (value >>> 14 | 0x80));
buffer.writeByte((byte) (value >>> 21 | 0x80));
buffer.writeByte((byte) (value >>> 28 | 0x80));
buffer.writeByte((byte) (value >>> 35 | 0x80));
buffer.writeByte((byte) (value >>> 42 | 0x80));
buffer.writeByte((byte) (value >>> 49));
return 8;
}
buffer.writeByte((byte) (value & 0x7F | 0x80));
buffer.writeByte((byte) (value >>> 7 | 0x80));
buffer.writeByte((byte) (value >>> 14 | 0x80));
buffer.writeByte((byte) (value >>> 21 | 0x80));
buffer.writeByte((byte) (value >>> 28 | 0x80));
buffer.writeByte((byte) (value >>> 35 | 0x80));
buffer.writeByte((byte) (value >>> 42 | 0x80));
buffer.writeByte((byte) (value >>> 49 | 0x80));
buffer.writeByte((byte) (value >>> 56));
return 9;
}
/**
* FROM KRYO
* <p>
* look at buffer, and see if we can read the length of the long off of it (from the reader index).
*
* @return 0 if we could not read anything, >0 for the number of bytes for the long on the buffer
*/
public static
int canReadLong(ByteBuf buffer) {
int position = buffer.readerIndex();
try {
int remaining = buffer.readableBytes();
for (int offset = 0, count = 1; offset < 64 && remaining > 0; offset += 7, remaining--, count++) {
int b = buffer.readByte();
if ((b & 0x80) == 0) {
return count;
}
}
return 0;
} finally {
buffer.readerIndex(position);
}
}
}

View File

@ -0,0 +1,397 @@
/*
* Copyright 2023 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.
*/
@file:Suppress("NAME_SHADOWING")
package dorkbox.bytes
import io.netty.buffer.ByteBuf
@Suppress("unused")
object OptimizeUtilsByteBuf {
// int
/**
* FROM KRYO
*
*
* Returns the number of bytes that would be written with [.writeInt].
*
* @param optimizePositive
* If true, small positive numbers will be more efficient (1 byte) and small negative numbers will be inefficient (5
* bytes). This ultimately means that it will use fewer bytes for positive numbers.
*/
fun intLength(value: Int, optimizePositive: Boolean): Int {
@Suppress("NAME_SHADOWING")
var value = value
if (!optimizePositive) {
value = value shl 1 xor (value shr 31)
}
if (value ushr 7 == 0) {
return 1
}
if (value ushr 14 == 0) {
return 2
}
if (value ushr 21 == 0) {
return 3
}
return if (value ushr 28 == 0) {
4
} else 5
}
/**
* FROM KRYO
*
*
* look at buffer, and see if we can read the length of the int off of it. (from the reader index)
*
* @return 0 if we could not read anything, >0 for the number of bytes for the int on the buffer
*/
fun canReadInt(buffer: ByteBuf): Int {
val startIndex = buffer.readerIndex()
return try {
var remaining = buffer.readableBytes()
var offset = 0
var count = 1
while (offset < 32 && remaining > 0) {
val b = buffer.readByte().toInt()
if (b and 0x80 == 0) {
return count
}
offset += 7
remaining--
count++
}
0
} finally {
buffer.readerIndex(startIndex)
}
}
fun canReadVarInt(buffer: ByteBuf): Boolean {
val startIndex = buffer.readerIndex()
try {
var remaining = buffer.readableBytes()
if (remaining >= 5) return true
var p = startIndex
if (buffer.getByte(p++).toInt() and 0x80 == 0) return true
if (p == remaining) return false
if (buffer.getByte(p++).toInt() and 0x80 == 0) return true
if (p == remaining) return false
if (buffer.getByte(p++).toInt() and 0x80 == 0) return true
if (p == remaining) return false
if (buffer.getByte(p++).toInt() and 0x80 == 0) return true
return if (p == remaining) false else true
} finally {
buffer.readerIndex(startIndex)
}
}
/**
* FROM KRYO
*
*
* Reads an int from the buffer that was optimized.
*
* @param optimizePositive
* If true, small positive numbers will be more efficient (1 byte) and small negative numbers will be inefficient (5
* bytes). This ultimately means that it will use fewer bytes for positive numbers.
*
* @return the number of bytes written.
*/
fun readInt(buffer: ByteBuf, optimizePositive: Boolean = false): Int {
var b = buffer.readByte().toInt()
var result = b and 0x7F
if (b and 0x80 != 0) {
b = buffer.readByte().toInt()
result = result or (b and 0x7F shl 7)
if (b and 0x80 != 0) {
b = buffer.readByte().toInt()
result = result or (b and 0x7F shl 14)
if (b and 0x80 != 0) {
b = buffer.readByte().toInt()
result = result or (b and 0x7F shl 21)
if (b and 0x80 != 0) {
b = buffer.readByte().toInt()
result = result or (b and 0x7F shl 28)
}
}
}
}
return if (optimizePositive) result else result ushr 1 xor -(result and 1)
}
/**
* FROM KRYO
*
*
* Writes the specified int to the buffer using 1 to 5 bytes, depending on the size of the number.
*
* @param optimizePositive
* If true, small positive numbers will be more efficient (1 byte) and small negative numbers will be inefficient (5
* bytes). This ultimately means that it will use fewer bytes for positive numbers.
*
* @return the number of bytes written.
*/
fun writeInt(buffer: ByteBuf, value: Int, optimizePositive: Boolean): Int {
var value = value
if (!optimizePositive) {
value = value shl 1 xor (value shr 31)
}
if (value ushr 7 == 0) {
buffer.writeByte(value.toByte().toInt())
return 1
}
if (value ushr 14 == 0) {
buffer.writeByte((value and 0x7F or 0x80).toByte().toInt())
buffer.writeByte((value ushr 7).toByte().toInt())
return 2
}
if (value ushr 21 == 0) {
buffer.writeByte((value and 0x7F or 0x80).toByte().toInt())
buffer.writeByte((value ushr 7 or 0x80).toByte().toInt())
buffer.writeByte((value ushr 14).toByte().toInt())
return 3
}
if (value ushr 28 == 0) {
buffer.writeByte((value and 0x7F or 0x80).toByte().toInt())
buffer.writeByte((value ushr 7 or 0x80).toByte().toInt())
buffer.writeByte((value ushr 14 or 0x80).toByte().toInt())
buffer.writeByte((value ushr 21).toByte().toInt())
return 4
}
buffer.writeByte((value and 0x7F or 0x80).toByte().toInt())
buffer.writeByte((value ushr 7 or 0x80).toByte().toInt())
buffer.writeByte((value ushr 14 or 0x80).toByte().toInt())
buffer.writeByte((value ushr 21 or 0x80).toByte().toInt())
buffer.writeByte((value ushr 28).toByte().toInt())
return 5
}
// long
/**
* Returns the 1-9 bytes that would be written with [.writeLong].
*
* @param optimizePositive
* If true, small positive numbers will be more efficient (1 byte) and small negative numbers will be inefficient (9
* bytes). This ultimately means that it will use fewer bytes for positive numbers.
*/
@JvmStatic
fun longLength(value: Long, optimizePositive: Boolean): Int {
var value = value
if (!optimizePositive) {
value = value shl 1 xor (value shr 63)
}
if (value ushr 7 == 0L) {
return 1
}
if (value ushr 14 == 0L) {
return 2
}
if (value ushr 21 == 0L) {
return 3
}
if (value ushr 28 == 0L) {
return 4
}
if (value ushr 35 == 0L) {
return 5
}
if (value ushr 42 == 0L) {
return 6
}
if (value ushr 49 == 0L) {
return 7
}
return if (value ushr 56 == 0L) {
8
} else 9
}
/**
* FROM KRYO
*
*
* Reads a 1-9 byte long.
*
* @param optimizePositive
* If true, small positive numbers will be more efficient (1 byte) and small negative numbers will be inefficient (9
* bytes). This ultimately means that it will use fewer bytes for positive numbers.
*/
fun readLong(buffer: ByteBuf, optimizePositive: Boolean): Long {
var b = buffer.readByte().toInt()
var result = (b and 0x7F).toLong()
if (b and 0x80 != 0) {
b = buffer.readByte().toInt()
result = result or (b and 0x7F shl 7).toLong()
if (b and 0x80 != 0) {
b = buffer.readByte().toInt()
result = result or (b and 0x7F shl 14).toLong()
if (b and 0x80 != 0) {
b = buffer.readByte().toInt()
result = result or (b and 0x7F shl 21).toLong()
if (b and 0x80 != 0) {
b = buffer.readByte().toInt()
result = result or ((b and 0x7F).toLong() shl 28)
if (b and 0x80 != 0) {
b = buffer.readByte().toInt()
result = result or ((b and 0x7F).toLong() shl 35)
if (b and 0x80 != 0) {
b = buffer.readByte().toInt()
result = result or ((b and 0x7F).toLong() shl 42)
if (b and 0x80 != 0) {
b = buffer.readByte().toInt()
result = result or ((b and 0x7F).toLong() shl 49)
if (b and 0x80 != 0) {
b = buffer.readByte().toInt()
result = result or (b.toLong() shl 56)
}
}
}
}
}
}
}
}
if (!optimizePositive) {
result = result ushr 1 xor -(result and 1L)
}
return result
}
/**
* FROM KRYO
*
*
* Writes a 1-9 byte long.
*
* @param optimizePositive
* If true, small positive numbers will be more efficient (1 byte) and small negative numbers will be inefficient (9
* bytes). This ultimately means that it will use fewer bytes for positive numbers.
*
* @return the number of bytes written.
*/
fun writeLong(buffer: ByteBuf, value: Long, optimizePositive: Boolean): Int {
var value = value
if (!optimizePositive) {
value = value shl 1 xor (value shr 63)
}
if (value ushr 7 == 0L) {
buffer.writeByte(value.toByte().toInt())
return 1
}
if (value ushr 14 == 0L) {
buffer.writeByte((value and 0x7FL or 0x80L).toByte().toInt())
buffer.writeByte((value ushr 7).toByte().toInt())
return 2
}
if (value ushr 21 == 0L) {
buffer.writeByte((value and 0x7FL or 0x80L).toByte().toInt())
buffer.writeByte((value ushr 7 or 0x80L).toByte().toInt())
buffer.writeByte((value ushr 14).toByte().toInt())
return 3
}
if (value ushr 28 == 0L) {
buffer.writeByte((value and 0x7FL or 0x80L).toByte().toInt())
buffer.writeByte((value ushr 7 or 0x80L).toByte().toInt())
buffer.writeByte((value ushr 14 or 0x80L).toByte().toInt())
buffer.writeByte((value ushr 21).toByte().toInt())
return 4
}
if (value ushr 35 == 0L) {
buffer.writeByte((value and 0x7FL or 0x80L).toByte().toInt())
buffer.writeByte((value ushr 7 or 0x80L).toByte().toInt())
buffer.writeByte((value ushr 14 or 0x80L).toByte().toInt())
buffer.writeByte((value ushr 21 or 0x80L).toByte().toInt())
buffer.writeByte((value ushr 28).toByte().toInt())
return 5
}
if (value ushr 42 == 0L) {
buffer.writeByte((value and 0x7FL or 0x80L).toByte().toInt())
buffer.writeByte((value ushr 7 or 0x80L).toByte().toInt())
buffer.writeByte((value ushr 14 or 0x80L).toByte().toInt())
buffer.writeByte((value ushr 21 or 0x80L).toByte().toInt())
buffer.writeByte((value ushr 28 or 0x80L).toByte().toInt())
buffer.writeByte((value ushr 35).toByte().toInt())
return 6
}
if (value ushr 49 == 0L) {
buffer.writeByte((value and 0x7FL or 0x80L).toByte().toInt())
buffer.writeByte((value ushr 7 or 0x80L).toByte().toInt())
buffer.writeByte((value ushr 14 or 0x80L).toByte().toInt())
buffer.writeByte((value ushr 21 or 0x80L).toByte().toInt())
buffer.writeByte((value ushr 28 or 0x80L).toByte().toInt())
buffer.writeByte((value ushr 35 or 0x80L).toByte().toInt())
buffer.writeByte((value ushr 42).toByte().toInt())
return 7
}
if (value ushr 56 == 0L) {
buffer.writeByte((value and 0x7FL or 0x80L).toByte().toInt())
buffer.writeByte((value ushr 7 or 0x80L).toByte().toInt())
buffer.writeByte((value ushr 14 or 0x80L).toByte().toInt())
buffer.writeByte((value ushr 21 or 0x80L).toByte().toInt())
buffer.writeByte((value ushr 28 or 0x80L).toByte().toInt())
buffer.writeByte((value ushr 35 or 0x80L).toByte().toInt())
buffer.writeByte((value ushr 42 or 0x80L).toByte().toInt())
buffer.writeByte((value ushr 49).toByte().toInt())
return 8
}
buffer.writeByte((value and 0x7FL or 0x80L).toByte().toInt())
buffer.writeByte((value ushr 7 or 0x80L).toByte().toInt())
buffer.writeByte((value ushr 14 or 0x80L).toByte().toInt())
buffer.writeByte((value ushr 21 or 0x80L).toByte().toInt())
buffer.writeByte((value ushr 28 or 0x80L).toByte().toInt())
buffer.writeByte((value ushr 35 or 0x80L).toByte().toInt())
buffer.writeByte((value ushr 42 or 0x80L).toByte().toInt())
buffer.writeByte((value ushr 49 or 0x80L).toByte().toInt())
buffer.writeByte((value ushr 56).toByte().toInt())
return 9
}
/**
* FROM KRYO
*
*
* look at buffer, and see if we can read the length of the long off of it (from the reader index).
*
* @return 0 if we could not read anything, >0 for the number of bytes for the long on the buffer
*/
fun canReadLong(buffer: ByteBuf): Int {
val position = buffer.readerIndex()
return try {
var remaining = buffer.readableBytes()
var offset = 0
var count = 1
while (offset < 64 && remaining > 0) {
val b = buffer.readByte().toInt()
if (b and 0x80 == 0) {
return count
}
offset += 7
remaining--
count++
}
0
} finally {
buffer.readerIndex(position)
}
}
}