209 lines
3.6 KiB
Kotlin
209 lines
3.6 KiB
Kotlin
package ru.dbotthepony.kstarbound.io
|
|
|
|
import it.unimi.dsi.fastutil.bytes.ByteArrayList
|
|
import java.io.IOException
|
|
import java.io.InputStream
|
|
import java.io.RandomAccessFile
|
|
|
|
/**
|
|
* Читает Variable Length Integer как Long
|
|
*/
|
|
fun RandomAccessFile.readVarLong(): Long {
|
|
var result = 0L
|
|
var read = read()
|
|
|
|
while (true) {
|
|
result = (result shl 7) or (read.toLong() and 0x7FL)
|
|
|
|
if (read and 0x80 == 0) {
|
|
break
|
|
}
|
|
|
|
read = read()
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
data class VarIntReadResult(val value: Int, val cells: Int)
|
|
|
|
/**
|
|
* Читает Variable Length Integer как Int
|
|
*/
|
|
fun RandomAccessFile.readVarInt(): Int {
|
|
var result = 0
|
|
var read = read()
|
|
|
|
while (true) {
|
|
result = (result shl 7) or (read and 0x7F)
|
|
|
|
if (read and 0x80 == 0) {
|
|
break
|
|
}
|
|
|
|
read = read()
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
/**
|
|
* Читает Variable Length Integer как Int
|
|
*/
|
|
fun RandomAccessFile.readVarIntInfo(): VarIntReadResult {
|
|
var result = 0
|
|
var read = read()
|
|
var i = 1
|
|
|
|
while (true) {
|
|
result = (result shl 7) or (read and 0x7F)
|
|
|
|
if (read and 0x80 == 0) {
|
|
break
|
|
}
|
|
|
|
read = read()
|
|
i++
|
|
}
|
|
|
|
return VarIntReadResult(result, i)
|
|
}
|
|
|
|
/**
|
|
* Читает Variable Length Integer как Int
|
|
*/
|
|
fun InputStream.readVarIntInfo(): VarIntReadResult {
|
|
var result = 0
|
|
var read = read()
|
|
var i = 1
|
|
|
|
while (true) {
|
|
result = (result shl 7) or (read and 0x7F)
|
|
|
|
if (read and 0x80 == 0) {
|
|
break
|
|
}
|
|
|
|
read = read()
|
|
i++
|
|
}
|
|
|
|
return VarIntReadResult(result, i)
|
|
}
|
|
|
|
/**
|
|
* Читает Variable Length Integer как Long
|
|
*/
|
|
fun InputStream.readVarLong(): Long {
|
|
var result = 0L
|
|
var read = read()
|
|
|
|
while (true) {
|
|
result = (result shl 7) or (read.toLong() and 0x7FL)
|
|
|
|
if (read and 0x80 == 0) {
|
|
break
|
|
}
|
|
|
|
read = read()
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
/**
|
|
* Читает Variable Length Integer как Int
|
|
*/
|
|
fun InputStream.readVarInt(): Int {
|
|
var result = 0
|
|
var read = read()
|
|
|
|
while (true) {
|
|
result = (result shl 7) or (read and 0x7F)
|
|
|
|
if (read and 0x80 == 0) {
|
|
break
|
|
}
|
|
|
|
read = read()
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
fun RandomAccessFile.readString(length: Int): String {
|
|
require(length >= 0) { "Invalid length $length" }
|
|
|
|
val bytes = ByteArray(length)
|
|
try {
|
|
readFully(bytes)
|
|
} catch(err: Throwable) {
|
|
throw IOException("Tried to read string with length of $length", err)
|
|
}
|
|
|
|
return bytes.toString(Charsets.UTF_8)
|
|
}
|
|
|
|
fun InputStream.readString(length: Int, allowSmaller: Boolean = false): String {
|
|
require(length >= 0) { "Invalid length $length" }
|
|
|
|
val bytes = ByteArray(length)
|
|
|
|
try {
|
|
val read = readNBytes(bytes, 0, length)
|
|
|
|
if (!allowSmaller)
|
|
require(read == bytes.size) { "Read $read bytes, expected ${bytes.size}" }
|
|
} catch(err: Throwable) {
|
|
throw IOException("Tried to read string with length of $length", err)
|
|
}
|
|
|
|
return bytes.toString(Charsets.UTF_8)
|
|
}
|
|
|
|
fun RandomAccessFile.readCString(): String {
|
|
val bytes = ByteArrayList()
|
|
var read = read()
|
|
|
|
while (read != 0) {
|
|
bytes.add(read.toByte())
|
|
read = read()
|
|
}
|
|
|
|
return ByteArray(bytes.size).also {
|
|
for (i in it.indices) {
|
|
it[i] = bytes.getByte(i)
|
|
}
|
|
}.toString(Charsets.UTF_8)
|
|
}
|
|
|
|
fun InputStream.readCString(): String {
|
|
val bytes = ByteArrayList()
|
|
var read = read()
|
|
|
|
while (read != 0) {
|
|
bytes.add(read.toByte())
|
|
read = read()
|
|
}
|
|
|
|
return ByteArray(bytes.size).also {
|
|
for (i in it.indices) {
|
|
it[i] = bytes.getByte(i)
|
|
}
|
|
}.toString(Charsets.UTF_8)
|
|
}
|
|
|
|
fun InputStream.readByteChar(): Char {
|
|
return read().toChar()
|
|
}
|
|
|
|
fun InputStream.readHeader(header: String) {
|
|
for ((i, char) in header.withIndex()) {
|
|
val read = readByteChar()
|
|
|
|
if (read != char) {
|
|
throw IllegalArgumentException("Malformed header at byte $i: expected $char (${char.code}) got $read (${char.code})")
|
|
}
|
|
}
|
|
}
|