Fix varint writing

This commit is contained in:
DBotThePony 2024-02-11 12:57:02 +07:00
parent 4b07f97168
commit 848c402246
Signed by: DBot
GPG Key ID: DCC23B5715498507
5 changed files with 156 additions and 14 deletions

View File

@ -20,9 +20,15 @@ val projectGroup: String by project
val projectVersion: String by project
val specifyKotlinAsDependency: String by project
val fastutilVersion: String by project
val jupiterVersion: String by project
tasks.test {
useJUnitPlatform()
}
dependencies {
testImplementation("org.jetbrains.kotlin:kotlin-test")
testImplementation("org.junit.jupiter:junit-jupiter:${jupiterVersion}")
implementation("it.unimi.dsi:fastutil:$fastutilVersion")
}

View File

@ -4,8 +4,9 @@ kotlin.code.style=official
specifyKotlinAsDependency=false
projectGroup=ru.dbotthepony.kommons
projectVersion=2.1.7
projectVersion=2.1.8
guavaDepVersion=33.0.0
gsonDepVersion=2.8.9
fastutilVersion=8.5.6
jupiterVersion=5.9.2

View File

@ -89,7 +89,7 @@ private fun readVarLongInfo(supplier: IntSupplier): VarLongReadResult {
throw EOFException()
while (true) {
result = (result shl 7) or (read.toLong() and 0x7F)
result = (result shl 7) or (read.toLong() and 0x7FL)
if (read and 0x80 == 0)
break
@ -154,22 +154,85 @@ private fun VarLongReadResult.fromSignedVar(): VarLongReadResult {
return VarLongReadResult(-(this.value ushr 1) - 1, this.cells)
}
/**
* Reads unsigned variable length integer, with Big-endian byte order
*/
fun RandomAccessFile.readVarLong() = readVarLong(::readUnsignedByte)
/**
* Reads unsigned variable length integer, with Big-endian byte order
*/
fun RandomAccessFile.readVarInt() = readVarInt(::readUnsignedByte)
/**
* Reads unsigned variable length integer, with Big-endian byte order
*/
fun RandomAccessFile.readVarLongInfo() = readVarLongInfo(::readUnsignedByte)
/**
* Reads unsigned variable length integer, with Big-endian byte order
*/
fun RandomAccessFile.readVarIntInfo() = readVarIntInfo(::readUnsignedByte)
/**
* Reads unsigned variable length integer, with Big-endian byte order
*/
fun InputStream.readVarLong() = readVarLong(::read)
/**
* Reads unsigned variable length integer, with Big-endian byte order
*/
fun InputStream.readVarInt() = readVarInt(::read)
/**
* Reads unsigned variable length integer, with Big-endian byte order
*/
fun InputStream.readVarLongInfo() = readVarLongInfo(::read)
/**
* Reads unsigned variable length integer, with Big-endian byte order
*/
fun InputStream.readVarIntInfo() = readVarIntInfo(::read)
/**
* Reads signed variable length integer, with Big-endian byte order
*/
fun RandomAccessFile.readSignedVarLong() = readVarLong(::readUnsignedByte).fromSignedVar()
/**
* Reads signed variable length integer, with Big-endian byte order
*/
fun RandomAccessFile.readSignedVarInt() = readVarInt(::readUnsignedByte).fromSignedVar()
/**
* Reads signed variable length integer, with Big-endian byte order
*/
fun RandomAccessFile.readSignedVarLongInfo() = readVarLongInfo(::readUnsignedByte).fromSignedVar()
/**
* Reads signed variable length integer, with Big-endian byte order
*/
fun RandomAccessFile.readSignedVarIntInfo() = readVarIntInfo(::readUnsignedByte).fromSignedVar()
/**
* Reads signed variable length integer, with Big-endian byte order
*/
fun InputStream.readSignedVarLong() = readVarLong(::read).fromSignedVar()
/**
* Reads signed variable length integer, with Big-endian byte order
*/
fun InputStream.readSignedVarInt() = readVarInt(::read).fromSignedVar()
/**
* Reads signed variable length integer, with Big-endian byte order
*/
fun InputStream.readSignedVarLongInfo() = readVarLongInfo(::read).fromSignedVar()
/**
* Reads signed variable length integer, with Big-endian byte order
*/
fun InputStream.readSignedVarIntInfo() = readVarIntInfo(::read).fromSignedVar()
fun InputStream.readBinaryString(): String {

View File

@ -83,22 +83,25 @@ fun OutputStream.writeFloat(value: Float) = writeInt(value.toBits())
fun OutputStream.writeDouble(value: Double) = writeLong(value.toBits())
private fun writeVarLong(write: IntConsumer, value: Long): Int {
var value = value
var i = 0
var length = 9
do {
val toWrite = (value and 0x7F).toInt()
value = value ushr 7
while (length > 0) {
val octetsPresent = (value ushr (length * 7)) and 0x7FL
if (value == 0L)
write.accept(toWrite)
else
write.accept(toWrite or 0x80)
if (octetsPresent != 0L) {
break
} else {
length--
}
}
i++
} while (value != 0L)
for (octet in length downTo 1) {
write.accept(((value ushr (octet * 7)) and 0x7FL).toInt() or 0x80)
}
return i
write.accept((value and 0x7FL).toInt())
return length + 1
}
private fun writeVarInt(write: IntConsumer, value: Int): Int {
@ -119,14 +122,45 @@ private fun Long.toSignedVar(): Long {
return ((-this - 1) shl 1) or 1L
}
/**
* Writes unsigned variable length integer, with Big-endian byte order
*/
fun RandomAccessFile.writeVarLong(value: Long) = writeVarLong(::write, value)
/**
* Writes unsigned variable length integer, with Big-endian byte order
*/
fun RandomAccessFile.writeVarInt(value: Int) = writeVarInt(::write, value)
/**
* Writes unsigned variable length integer, with Big-endian byte order
*/
fun OutputStream.writeVarLong(value: Long) = writeVarLong(::write, value)
/**
* Writes unsigned variable length integer, with Big-endian byte order
*/
fun OutputStream.writeVarInt(value: Int) = writeVarInt(::write, value)
/**
* Writes signed variable length integer, with Big-endian byte order
*/
fun RandomAccessFile.writeSignedVarLong(value: Long) = writeVarLong(::write, value.toSignedVar())
/**
* Writes signed variable length integer, with Big-endian byte order
*/
fun RandomAccessFile.writeSignedVarInt(value: Int) = writeVarInt(::write, value.toSignedVar())
/**
* Writes signed variable length integer, with Big-endian byte order
*/
fun OutputStream.writeSignedVarLong(value: Long) = writeVarLong(::write, value.toSignedVar())
/**
* Writes signed variable length integer, with Big-endian byte order
*/
fun OutputStream.writeSignedVarInt(value: Int) = writeVarInt(::write, value.toSignedVar())
fun OutputStream.writeBinaryString(input: String) {

View File

@ -0,0 +1,38 @@
package ru.dbotthepony.kommons.test
import it.unimi.dsi.fastutil.io.FastByteArrayInputStream
import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream
import org.junit.jupiter.api.Test
import ru.dbotthepony.kommons.io.readVarInt
import ru.dbotthepony.kommons.io.readVarIntInfo
import ru.dbotthepony.kommons.io.writeVarInt
import kotlin.test.assertEquals
object StreamTests {
private fun readWrite(value: Int) {
val output = FastByteArrayOutputStream()
val input = FastByteArrayInputStream(output.array, 0, output.length)
val r = input.readVarIntInfo()
assertEquals(value, r.value)
}
@Test
fun varInts() {
readWrite(0)
readWrite(1)
readWrite(2)
readWrite(3)
readWrite(63)
readWrite(64)
readWrite(65)
readWrite(120)
readWrite(121)
readWrite(126)
readWrite(127)
readWrite(128)
readWrite(129)
readWrite(254)
readWrite(255)
readWrite(256)
}
}