Added some variants to readers

This commit is contained in:
DBotThePony 2022-02-21 21:47:51 +07:00
parent a3282098b1
commit 66d7a267b2
Signed by: DBot
GPG Key ID: DCC23B5715498507
2 changed files with 130 additions and 2 deletions

View File

@ -1,10 +1,12 @@
package ru.dbotthepony.kstarbound.io
import com.google.gson.*
import java.io.DataInputStream
import java.io.InputStream
import java.io.RandomAccessFile
/**
* Интерфейс для чтения и записи двоичного формата Json от Chucklefish
* Represents interface to read binary json format by Chucklefish
*/
object BinaryJson {
const val TYPE_NULL = 0x01
@ -25,7 +27,40 @@ object BinaryJson {
TYPE_NULL -> JsonNull.INSTANCE
TYPE_DOUBLE -> JsonPrimitive(reader.readDouble())
TYPE_BOOLEAN -> JsonPrimitive(reader.readBoolean())
TYPE_INT -> JsonPrimitive(reader.readVarLong())
TYPE_INT -> {
var read = reader.readVarLong()
val sign = read and 0x1L
read = read ushr 1
if (sign == 1L) {
JsonPrimitive(read - 1L)
} else {
JsonPrimitive(read)
}
}
TYPE_STRING -> JsonPrimitive(reader.readASCIIString(reader.readVarInt()))
TYPE_ARRAY -> readArray(reader)
TYPE_OBJECT -> readObject(reader)
else -> throw JsonParseException("Unknown element type $id")
}
}
fun readElement(reader: DataInputStream): JsonElement {
return when (val id = reader.read()) {
TYPE_NULL -> JsonNull.INSTANCE
TYPE_DOUBLE -> JsonPrimitive(reader.readDouble())
TYPE_BOOLEAN -> JsonPrimitive(reader.readBoolean())
TYPE_INT -> {
var read = reader.readVarLong()
val sign = read and 0x1L
read = read ushr 1
if (sign == 1L) {
JsonPrimitive(read - 1L)
} else {
JsonPrimitive(read)
}
}
TYPE_STRING -> JsonPrimitive(reader.readASCIIString(reader.readVarInt()))
TYPE_ARRAY -> readArray(reader)
TYPE_OBJECT -> readObject(reader)
@ -65,6 +100,38 @@ object BinaryJson {
return build
}
fun readObject(reader: DataInputStream): JsonObject {
val values = reader.readVarInt() - 1
if (values == -1) {
return JsonObject()
}
if (values < -1) {
throw JsonParseException("Tried to read json object with $values elements in it")
}
val build = JsonObject()
for (i in 0 .. values) {
val key: String
try {
key = reader.readASCIIString(reader.readVarInt())
} catch(err: Throwable) {
throw JsonParseException("Reading json object at $i", err)
}
try {
build.add(key, readElement(reader))
} catch(err: Throwable) {
throw JsonParseException("Reading json object at $i with name $key", err)
}
}
return build
}
fun readArray(reader: RandomAccessFile): JsonArray {
val values = reader.readVarInt() - 1
@ -84,4 +151,24 @@ object BinaryJson {
return build
}
fun readArray(reader: DataInputStream): JsonArray {
val values = reader.readVarInt() - 1
if (values == -1) {
return JsonArray()
}
if (values < -1) {
throw JsonParseException("Tried to read json array with $values elements in it")
}
val build = JsonArray()
for (i in 0 .. values) {
build.add(readElement(reader))
}
return build
}
}

View File

@ -1,5 +1,6 @@
package ru.dbotthepony.kstarbound.io
import java.io.DataInputStream
import java.io.IOException
import java.io.InputStream
import java.io.RandomAccessFile
@ -44,6 +45,46 @@ fun RandomAccessFile.readVarInt(): Int {
return result
}
/**
* Читает 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.readASCIIString(length: Int): String {
require(length >= 0) { "Invalid length $length" }