Update variable length ints to accept negative values

This commit is contained in:
DBotThePony 2022-09-26 10:18:06 +07:00
parent 8a238c2eaa
commit 8150481081
Signed by: DBot
GPG Key ID: DCC23B5715498507
3 changed files with 149 additions and 44 deletions

View File

@ -7,6 +7,7 @@ import java.io.InputStream
import java.io.OutputStream
import java.util.*
import java.util.function.Predicate
import kotlin.math.absoluteValue
interface IStreamCodec<V> {
fun read(stream: DataInputStream): V
@ -134,59 +135,79 @@ fun OutputStream.writeDouble(value: Double) = writeLong(value.toBits())
fun InputStream.readDouble() = Double.fromBits(readLong())
fun InputStream.readVarIntLE(): Int {
var result = 0
var read = read()
var i = 0
val readFirst = read()
while (read and 128 != 0) {
result = result or ((read and 127) shl i)
read = read()
i += 7
if (readFirst and 64 == 0) {
return if (readFirst and 128 != 0) -(readFirst and 63) else readFirst and 63
}
result = result or ((read and 127) shl i)
var result = 0
var nextBit = readFirst and 64
var read = readFirst and 63
var i = 0
return result
while (nextBit != 0) {
result = result or (read shl i)
read = read()
nextBit = read and 128
read = read and 127
if (i == 0)
i = 6
else
i += 7
}
result = result or (read shl i)
return if (readFirst and 128 != 0) -result else result
}
fun OutputStream.writeVarIntLE(value: Int) {
require(value >= 0) { "Negative number provided: $value" }
var written = value
write((if (value < 0) 128 else 0) or (if (value in -63 .. 63) 0 else 64) or (value.absoluteValue and 63))
var written = value.absoluteValue ushr 6
while (written >= 128) {
write((written and 127) or 128)
while (written != 0) {
write((written and 127) or (if (written >= 128) 128 else 0))
written = written ushr 7
}
write(written)
}
fun InputStream.readVarLongLE(): Long {
var result = 0L
var read = read()
var i = 0
val readFirst = read()
while (read and 128 != 0) {
result = result or ((read and 127) shl i).toLong()
read = read()
i += 7
if (readFirst and 64 == 0) {
return if (readFirst and 128 != 0) -(readFirst and 63).toLong() else (readFirst and 63).toLong()
}
result = result or ((read and 127) shl i).toLong()
var result = 0L
var nextBit = readFirst and 64
var read = readFirst and 63
var i = 0
return result
while (nextBit != 0) {
result = result or (read shl i).toLong()
read = read()
nextBit = read and 128
read = read and 127
if (i == 0)
i = 6
else
i += 7
}
result = result or (read shl i).toLong()
return if (readFirst and 128 != 0) -result else result
}
fun OutputStream.writeVarLongLE(value: Long) {
require(value >= 0L) { "Negative number provided: $value" }
var written = value
write((if (value < 0L) 128 else 0) or (if (value in -63 .. 63) 0 else 64) or (value.absoluteValue and 63).toInt())
var written = value.absoluteValue ushr 6
while (written >= 128) {
write(((written and 127) or 128).toInt())
while (written != 0L) {
write((written and 127).toInt() or (if (written >= 128) 128 else 0))
written = written ushr 7
}
write(written.toInt())
}
private data class IndexedStreamCodec<T>(

View File

@ -101,6 +101,14 @@ class FieldSynchronizer {
return Field(value, VarLongValueCodec, getter, setter)
}
fun fixedLong(
value: Long = 0L,
getter: FieldGetter<Long>? = null,
setter: FieldSetter<Long>? = null,
): Field<Long> {
return Field(value, LongValueCodec, getter, setter)
}
fun float(
value: Float = 0f,
getter: FieldGetter<Float>? = null,
@ -133,6 +141,14 @@ class FieldSynchronizer {
return Field(value, VarIntValueCodec, getter, setter)
}
fun fixedInt(
value: Int = 0,
getter: FieldGetter<Int>? = null,
setter: FieldSetter<Int>? = null,
): Field<Int> {
return Field(value, IntValueCodec, getter, setter)
}
fun fraction(
value: ImpreciseFraction = ImpreciseFraction.ZERO,
getter: FieldGetter<ImpreciseFraction>? = null,

View File

@ -7,8 +7,10 @@ import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import ru.dbotthepony.mc.otm.core.readInt
import ru.dbotthepony.mc.otm.core.readVarIntLE
import ru.dbotthepony.mc.otm.core.readVarLongLE
import ru.dbotthepony.mc.otm.core.writeInt
import ru.dbotthepony.mc.otm.core.writeVarIntLE
import ru.dbotthepony.mc.otm.core.writeVarLongLE
object FriendlyStreams {
@Test
@ -32,22 +34,88 @@ object FriendlyStreams {
output.writeVarIntLE(10023)
output.writeVarIntLE(100000)
output.writeVarIntLE(-0)
output.writeVarIntLE(-1)
output.writeVarIntLE(-4)
output.writeVarIntLE(-15)
output.writeVarIntLE(-16)
output.writeVarIntLE(-127)
output.writeVarIntLE(-128)
output.writeVarIntLE(-129)
output.writeVarIntLE(-10023)
output.writeVarIntLE(-100000)
output.writeVarLongLE(0)
output.writeVarLongLE(1)
output.writeVarLongLE(4)
output.writeVarLongLE(15)
output.writeVarLongLE(16)
output.writeVarLongLE(127)
output.writeVarLongLE(128)
output.writeVarLongLE(129)
output.writeVarLongLE(10023)
output.writeVarLongLE(100000)
output.writeVarLongLE(-0)
output.writeVarLongLE(-1)
output.writeVarLongLE(-4)
output.writeVarLongLE(-15)
output.writeVarLongLE(-16)
output.writeVarLongLE(-127)
output.writeVarLongLE(-128)
output.writeVarLongLE(-129)
output.writeVarLongLE(-10023)
output.writeVarLongLE(-100000)
val input = FastByteArrayInputStream(output.array, 0, output.length)
assertEquals(input.readInt(), 4)
assertEquals(input.readInt(), 16)
assertEquals(input.readInt(), -1)
assertEquals(input.readInt(), 1000000)
assertEquals(4, input.readInt())
assertEquals(16, input.readInt())
assertEquals(-1, input.readInt())
assertEquals(1000000, input.readInt())
assertEquals(input.readVarIntLE(), 0)
assertEquals(input.readVarIntLE(), 1)
assertEquals(input.readVarIntLE(), 4)
assertEquals(input.readVarIntLE(), 15)
assertEquals(input.readVarIntLE(), 16)
assertEquals(input.readVarIntLE(), 127)
assertEquals(input.readVarIntLE(), 128)
assertEquals(input.readVarIntLE(), 129)
assertEquals(input.readVarIntLE(), 10023)
assertEquals(input.readVarIntLE(), 100000)
assertEquals(0, input.readVarIntLE())
assertEquals(1, input.readVarIntLE())
assertEquals(4, input.readVarIntLE())
assertEquals(15, input.readVarIntLE())
assertEquals(16, input.readVarIntLE())
assertEquals(127, input.readVarIntLE())
assertEquals(128, input.readVarIntLE())
assertEquals(129, input.readVarIntLE())
assertEquals(10023, input.readVarIntLE())
assertEquals(100000, input.readVarIntLE())
assertEquals(-0, input.readVarIntLE())
assertEquals(-1, input.readVarIntLE())
assertEquals(-4, input.readVarIntLE())
assertEquals(-15, input.readVarIntLE())
assertEquals(-16, input.readVarIntLE())
assertEquals(-127, input.readVarIntLE())
assertEquals(-128, input.readVarIntLE())
assertEquals(-129, input.readVarIntLE())
assertEquals(-10023, input.readVarIntLE())
assertEquals(-100000, input.readVarIntLE())
assertEquals(0, input.readVarLongLE())
assertEquals(1, input.readVarLongLE())
assertEquals(4, input.readVarLongLE())
assertEquals(15, input.readVarLongLE())
assertEquals(16, input.readVarLongLE())
assertEquals(127, input.readVarLongLE())
assertEquals(128, input.readVarLongLE())
assertEquals(129, input.readVarLongLE())
assertEquals(10023, input.readVarLongLE())
assertEquals(100000, input.readVarLongLE())
assertEquals(-0, input.readVarLongLE())
assertEquals(-1, input.readVarLongLE())
assertEquals(-4, input.readVarLongLE())
assertEquals(-15, input.readVarLongLE())
assertEquals(-16, input.readVarLongLE())
assertEquals(-127, input.readVarLongLE())
assertEquals(-128, input.readVarLongLE())
assertEquals(-129, input.readVarLongLE())
assertEquals(-10023, input.readVarLongLE())
assertEquals(-100000, input.readVarLongLE())
}
}