Bimba.git

ref: 093bbcead898be4e5123730fd87b2d88bdaa9696

app/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
package xyz.apiote.fruchtfleisch

import java.io.EOFException
import java.io.InputStream
import java.lang.Double.longBitsToDouble
import java.lang.Float.intBitsToFloat

class Reader(private val stream: InputStream) {
	fun readUInt(): ULong {
		var result: ULong = 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
			}
			i++
			s += 7
		}
		return result
	}

	fun readInt(): Long {
		val unsigned = readUInt()
		var signed = unsigned.shr(1).toLong()
		if (unsigned.and(1UL) != 0UL) {
			signed = signed.inv()
		}
		return 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(length: UByte): ByteArray {
		val n = length.toInt()
		val data = ByteArray(n)
		var left = n
		while (left > 0) {
			val r = stream.read(data, n - left, left)
			left -= r
		}
		return data
	}

	fun readString(): String {
		val length = readU8()
		return readData(length).decodeToString()
	}

	fun readBoolean(): Boolean {
		return when (readU8().toUInt()) {
			0u -> false
			1u -> true
			else -> TODO("throw wrong value")
		}
	}
}