72 lines
1.7 KiB
Kotlin

package net.sergeych.lynon
abstract class BitInput {
/**
* Return next byte, int in 0..255 range, or -1 if end of stream reached
*/
abstract fun getByte(): Int
private var accumulator = 0
var isEndOfStream: Boolean = false
private set
private var mask = 0
fun getBitOrNull(): Int? {
if (isEndOfStream) return null
if (mask == 0) {
accumulator = getByte()
if (accumulator == -1) {
isEndOfStream = true
return null
}
mask = 0x80
}
val result = if (0 == accumulator and mask) 0 else 1
mask = mask shr 1
return result
}
fun getBitsOrNull(count: Int): ULong? {
var result = 0UL
var mask = 1UL
for( i in 0 ..< count) {
when(getBitOrNull()) {
null -> return null
1 -> result = result or mask
0 -> {}
}
mask = mask shl 1
}
return result
}
fun getBits(count: Int): ULong {
return getBitsOrNull(count) ?: throw IllegalStateException("Unexpected end of stream")
}
fun getBit(): Int {
return getBitOrNull() ?: throw IllegalStateException("Unexpected end of stream")
}
fun unpackUnsigned(): ULong {
val tetrades = getBits(4).toInt()
var result = 0UL
var shift = 0
for (i in 0..<tetrades) {
result = result or (getBits(4) shl shift)
shift += 4
}
return result
}
fun unpackSigned(): Long {
val isNegative = getBit()
val value = unpackUnsigned().toLong()
return if( isNegative == 1) -value else value
}
}