ref: v3.6.1
fruchtfleisch/src/main/java/xyz/apiote/fruchtfleisch/Reader.kt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
// SPDX-FileCopyrightText: Adam Evyčędo // // SPDX-License-Identifier: GPL-3.0-or-later package xyz.apiote.fruchtfleisch import java.io.EOFException import java.io.InputStream import java.lang.Double.longBitsToDouble import java.lang.Float.intBitsToFloat @Suppress("MemberVisibilityCanBePrivate", "unused", "BooleanMethodIsAlwaysInverted") class Reader(private val stream: InputStream) { fun readUInt(): UIntVar { var result = 0UL var i = 0 var s = 0 while (true) { val b = stream.read() if (b < 0) { throw EOFException("while reading byte") } if (b < 0x80) { if (i > 9 || (i == 9 && b > 1)) { TODO("throw int overflow") } result = result.or(b.toULong().shl(s)) break } result = result.or(b.toULong().and(127u).shl(s)) i++ s += 7 } return UIntVar(result) } fun readInt(): IntVar { val unsigned = readUInt().toULong() var signed = unsigned.shr(1).toLong() if (unsigned.and(1UL) != 0UL) { signed = signed.inv() } return IntVar(signed) } fun readU8(): UByte { val b = stream.read() if (b < 0) { throw EOFException("while reading byte") } return b.toUByte() } fun readU16(): UShort { val b1 = readU8() val b2 = readU8() return (b2.toUInt().shl(8) or b1.toUInt()).toUShort() } fun readU32(): UInt { val b1 = readU8() val b2 = readU8() val b3 = readU8() val b4 = readU8() return b4.toUInt().shl(24) or b3.toUInt().shl(16) or b2.toUInt().shl(8) or b1.toUInt() } fun readU64(): ULong { val b1 = readU8() val b2 = readU8() val b3 = readU8() val b4 = readU8() val b5 = readU8() val b6 = readU8() val b7 = readU8() val b8 = readU8() return b8.toULong().shl(56) or b7.toULong().shl(48) or b6.toULong().shl(40) or b5.toULong().shl(32) or b4.toULong().shl(24) or b3.toULong().shl(16) or b2.toULong().shl(8) or b1.toULong() } fun readI8(): Byte { return readU8().toByte() } fun readI16(): Short { return readU16().toShort() } fun readI32(): Int { return readU32().toInt() } fun readI64(): Long { return readU64().toLong() } fun readFloat32(): Float { return intBitsToFloat(readI32()) } fun readFloat64(): Double { return longBitsToDouble(readI64()) } fun readData(n: Int): ByteArray { val data = ByteArray(n) var left = n while (left > 0) { val r = stream.read(data, n - left, left) if (r == -1) { break } left -= r } return data } fun readString(): String { val length = readUInt() return readData(length.toULong().toInt()).decodeToString() } fun readBoolean(): Boolean { return when (readU8().toUInt()) { 0u -> false 1u -> true else -> TODO("throw wrong value") } } } |