Author: Adam <git@apiote.xyz>
separate fruchtfleisch
app/build.gradle | 1 app/src/main/java/ml/adamsprogs/bimba/api/Structs.kt | 26 +++++++------- | 22 +++++++---- fruchtfleisch/.gitignore | 1 fruchtfleisch/build.gradle | 12 ++++++ settings.gradle | 1
diff --git a/app/build.gradle b/app/build.gradle index 17900722ec9d39dd0fec456fe6dd9ddf51c1d563..1a662a0534d8f697626dc54fd004c57425213f57 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -50,6 +50,7 @@ implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation 'androidx.core:core-splashscreen:1.0.0' implementation 'com.google.openlocationcode:openlocationcode:1.0.4' implementation 'org.osmdroid:osmdroid-android:6.1.14' + implementation project(path: ':fruchtfleisch') testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' diff --git a/app/src/main/java/ml/adamsprogs/bimba/api/Structs.kt b/app/src/main/java/ml/adamsprogs/bimba/api/Structs.kt index 18f77b37bc4e46641615a2bedf43204dc38f5bb6..dda6d449bd2ae9a070db87193dbcab646f270986 100644 --- a/app/src/main/java/ml/adamsprogs/bimba/api/Structs.kt +++ b/app/src/main/java/ml/adamsprogs/bimba/api/Structs.kt @@ -32,7 +32,7 @@ override fun toString(): String = "$latitude,$longitude" companion object { fun unmarshal(stream: InputStream): Position { - val reader = Reader(stream) + val reader = xyz.apiote.fruchtfleisch.Reader(stream) return Position( reader.readFloat64(), reader.readFloat64() @@ -91,7 +91,7 @@ val lastUpdate: DateTime ) { companion object { fun unmarshal(stream: InputStream): FeedInfo { - val reader = Reader(stream) + val reader = xyz.apiote.fruchtfleisch.Reader(stream) return FeedInfo( reader.readString(), reader.readString(), @@ -112,7 +112,7 @@ val Effect: UInt ) { companion object { fun unmarshal(stream: InputStream): Alert { - val reader = Reader(stream) + val reader = xyz.apiote.fruchtfleisch.Reader(stream) val header = reader.readString() val description = reader.readString() val url = reader.readString() @@ -132,7 +132,7 @@ val Zone: String ) { companion object { fun unmarshal(stream: InputStream): Time { - val reader = Reader(stream) + val reader = xyz.apiote.fruchtfleisch.Reader(stream) return Time( reader.readUInt().toUInt(), reader.readUInt().toUInt(), @@ -147,7 +147,7 @@ data class Colour(val R: UByte, val G: UByte, val B: UByte) { companion object { fun unmarshal(stream: InputStream): Colour { - val reader = Reader(stream) + val reader = xyz.apiote.fruchtfleisch.Reader(stream) return Colour( reader.readU8(), reader.readU8(), @@ -222,7 +222,7 @@ } companion object { fun unmarshal(stream: InputStream): Vehicle { - val reader = Reader(stream) + val reader = xyz.apiote.fruchtfleisch.Reader(stream) return Vehicle( reader.readString(), Position.unmarshal(stream), @@ -248,7 +248,7 @@ val name: String ) : LineAbstract { companion object { fun unmarshal(stream: InputStream): LineStub { - val reader = Reader(stream) + val reader = xyz.apiote.fruchtfleisch.Reader(stream) val colour = Colour.unmarshal(stream) val type = reader.readUInt() val name = reader.readString() @@ -326,7 +326,7 @@ } companion object { fun unmarshal(stream: InputStream): Departure { - val reader = Reader(stream) + val reader = xyz.apiote.fruchtfleisch.Reader(stream) val id = reader.readString() val line = LineStub.unmarshal(stream) val headsign = reader.readString() @@ -414,7 +414,7 @@ } companion object { fun unmarshal(stream: InputStream): Stop { - val reader = Reader(stream) + val reader = xyz.apiote.fruchtfleisch.Reader(stream) val code = reader.readString() val zone = reader.readString() val position = Position.unmarshal(stream) @@ -545,7 +545,7 @@ } companion object { fun unmarshal(stream: InputStream): Line { - val reader = Reader(stream) + val reader = xyz.apiote.fruchtfleisch.Reader(stream) val colour = Colour.unmarshal(stream) val type = reader.readUInt() val headsignsThereNum = reader.readUInt() @@ -587,7 +587,7 @@ data class ChangeOption(val line: String, val headsign: String) { companion object { fun unmarshal(stream: InputStream): ChangeOption { - val reader = Reader(stream) + val reader = xyz.apiote.fruchtfleisch.Reader(stream) return ChangeOption(line = reader.readString(), headsign = reader.readString()) } } @@ -600,7 +600,7 @@ val prevNodes: Map> ) { companion object { fun unmarshal(stream: InputStream): LineGraph { - val reader = Reader(stream) + val reader = xyz.apiote.fruchtfleisch.Reader(stream) val stopsNum = reader.readUInt() val stops = mutableListOf<StopStub>() for (i in 0UL until stopsNum) { @@ -637,7 +637,7 @@ data class StopStub(val name: String, val code: String, val zone: String, val onDemand: Boolean) { companion object { fun unmarshal(stream: InputStream): StopStub { - val reader = Reader(stream) + val reader = xyz.apiote.fruchtfleisch.Reader(stream) return StopStub( code = reader.readString(), name = reader.readString(), diff --git a/app/src/main/java/xyz/apiote/fruchtfleisch/Reader.kt b/app/src/main/java/xyz/apiote/fruchtfleisch/Reader.kt deleted file mode 100644 index 77921d8841da356c489f7c19f7576691ab1fe2f1..0000000000000000000000000000000000000000 --- a/app/src/main/java/xyz/apiote/fruchtfleisch/Reader.kt +++ /dev/null @@ -1,122 +0,0 @@ -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(): 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") - } - } -} \ No newline at end of file diff --git a/fruchtfleisch/.gitignore b/fruchtfleisch/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..42afabfd2abebf31384ca7797186a27a4b7dbee8 --- /dev/null +++ b/fruchtfleisch/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/fruchtfleisch/build.gradle b/fruchtfleisch/build.gradle new file mode 100644 index 0000000000000000000000000000000000000000..b1a7126119782ae28a7a75086af3235f2619292e --- /dev/null +++ b/fruchtfleisch/build.gradle @@ -0,0 +1,12 @@ +plugins { + id 'java-library' + id 'org.jetbrains.kotlin.jvm' +} + +java { + sourceCompatibility = JavaVersion.VERSION_1_7 + targetCompatibility = JavaVersion.VERSION_1_7 +} +dependencies { + implementation 'org.jetbrains.kotlin:kotlin-reflect:1.8.10' +} \ No newline at end of file diff --git a/fruchtfleisch/src/main/java/xyz/apiote/fruchtfleisch/Reader.kt b/fruchtfleisch/src/main/java/xyz/apiote/fruchtfleisch/Reader.kt new file mode 100644 index 0000000000000000000000000000000000000000..9d49df734169f7b2934d7897e89311653de7139c --- /dev/null +++ b/fruchtfleisch/src/main/java/xyz/apiote/fruchtfleisch/Reader.kt @@ -0,0 +1,128 @@ +package xyz.apiote.fruchtfleisch + +import java.io.EOFException +import java.io.InputStream +import java.lang.Double.longBitsToDouble +import java.lang.Float.intBitsToFloat + +data class IntVar(private val v: Long) { + fun toLong() = v +} +data class UIntVar(private val v: ULong) { + fun toULong() = v +} + +@Suppress("MemberVisibilityCanBePrivate", "unused", "BooleanMethodIsAlwaysInverted") +class Reader(private val stream: InputStream) { + fun readUInt(): UIntVar { + 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 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) + left -= r + } + return data + } + + fun readString(): String { + val length = readU8() + return readData(length.toInt()).decodeToString() + } + + fun readBoolean(): Boolean { + return when (readU8().toUInt()) { + 0u -> false + 1u -> true + else -> TODO("throw wrong value") + } + } +} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 726f36ccf0807b77f23a976e0c7e80d437baeac8..65d6741bf7ac4b9016dfb6c839a41deb33027086 100644 --- a/settings.gradle +++ b/settings.gradle @@ -15,3 +15,4 @@ } } rootProject.name = "Bimba" include ':app' +include ':fruchtfleisch'