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

View File

@ -101,6 +101,14 @@ class FieldSynchronizer {
return Field(value, VarLongValueCodec, getter, setter) 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( fun float(
value: Float = 0f, value: Float = 0f,
getter: FieldGetter<Float>? = null, getter: FieldGetter<Float>? = null,
@ -133,6 +141,14 @@ class FieldSynchronizer {
return Field(value, VarIntValueCodec, getter, setter) 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( fun fraction(
value: ImpreciseFraction = ImpreciseFraction.ZERO, value: ImpreciseFraction = ImpreciseFraction.ZERO,
getter: FieldGetter<ImpreciseFraction>? = null, getter: FieldGetter<ImpreciseFraction>? = null,

View File

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