SASPlanet sqlite parser
This commit is contained in:
parent
d1bf25b9c9
commit
516455209e
4 changed files with 98 additions and 2 deletions
|
|
@ -29,6 +29,7 @@ class KhmParser {
|
|||
ctx.openFileOutput(HEIGHT_FILE, Context.MODE_PRIVATE).use {
|
||||
it.write(inp.readBytes())
|
||||
}
|
||||
inp.close()
|
||||
}
|
||||
|
||||
private fun getOffset(header: HeightInfo, x: Int, y: Int): Int {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.mirenkov.ktheightmap
|
|||
import android.app.Application
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
|
|
@ -22,10 +23,12 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import com.mirenkov.ktheightmap.parser.SasSQLiteParser
|
||||
import com.mirenkov.ktheightmap.ui.theme.KtHeightMapTheme
|
||||
import com.nareshchocha.filepickerlibrary.FilePickerResultContracts
|
||||
import com.nareshchocha.filepickerlibrary.models.DocumentFilePickerConfig
|
||||
import com.nareshchocha.filepickerlibrary.models.FilePickerResult
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import java.io.FileInputStream
|
||||
|
|
@ -102,6 +105,16 @@ fun SettingsMain(vm: TileViewModel, launcher: ActivityResultLauncher<DocumentFil
|
|||
KhmParser.load(it, ctx)
|
||||
} },
|
||||
) { Text(text = "Load .khm") }
|
||||
Button(
|
||||
onClick = {
|
||||
filePath?.let {
|
||||
coroutineScope.launch(Dispatchers.IO) {
|
||||
SasSQLiteParser.processZip(it, vm.repository, ctx)
|
||||
coroutineScope.launch(Dispatchers.Main) { Toast.makeText(ctx, "File parsed.", Toast.LENGTH_LONG).show() }
|
||||
}
|
||||
}
|
||||
}
|
||||
) { Text("Load SAS") }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -129,7 +142,7 @@ suspend fun processZip(filePath: String?): List<Tile> = coroutineScope {
|
|||
fun processEntry(zis: ZipInputStream, entry: ZipEntry): Tile {
|
||||
val ba = ByteArray(entry.size.toInt())
|
||||
var offset = 0
|
||||
var size = zis.read(ba, 0, ba.size)
|
||||
var size = zis.read(ba)
|
||||
while (size > 0) {
|
||||
offset += size
|
||||
size = zis.read(ba, offset, ba.size - offset)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,82 @@
|
|||
package com.mirenkov.ktheightmap.parser
|
||||
|
||||
import android.content.Context
|
||||
import android.database.Cursor
|
||||
import android.database.sqlite.SQLiteDatabase
|
||||
import android.util.Log
|
||||
import com.mirenkov.ktheightmap.TAG
|
||||
import com.mirenkov.ktheightmap.Tile
|
||||
import com.mirenkov.ktheightmap.TileRepository
|
||||
import com.mirenkov.ktheightmap.toBase64
|
||||
import java.io.FileInputStream
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipInputStream
|
||||
|
||||
// Parser for zipped sas.planet SQLite
|
||||
class SasSQLiteParser {
|
||||
companion object {
|
||||
private const val TEMP_DB_NAME: String = "temp.db"
|
||||
|
||||
fun processZip(filePath: String, repo: TileRepository, ctx: Context) {
|
||||
ZipInputStream(FileInputStream(filePath)).use { zis ->
|
||||
var entry = zis.nextEntry
|
||||
while(true) {
|
||||
if (entry.name.endsWith(".sqlitedb")) {
|
||||
processSqlite(zis, entry, repo, ctx)
|
||||
}
|
||||
entry = zis.nextEntry
|
||||
if (entry == null)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun processSqlite(zis: ZipInputStream, entry: ZipEntry, repo: TileRepository, ctx: Context) {
|
||||
val ba = ByteArray(entry.size.toInt())
|
||||
var offset = 0
|
||||
var size = zis.read(ba)
|
||||
while (size > 0) {
|
||||
offset += size
|
||||
size = zis.read(ba, offset, ba.size - offset)
|
||||
}
|
||||
|
||||
Log.i(TAG, entry.name)
|
||||
Log.i(TAG, entry.size.toString())
|
||||
Log.i(TAG, entry.compressedSize.toString())
|
||||
|
||||
val level = Regex("(?<=z)(\\d+)").find(entry.name)!!.value.toInt()
|
||||
|
||||
ctx.openFileOutput(TEMP_DB_NAME, Context.MODE_PRIVATE).use {
|
||||
it.write(ba)
|
||||
}
|
||||
|
||||
val path = ctx.getFileStreamPath(TEMP_DB_NAME).path
|
||||
val db = SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READONLY)
|
||||
|
||||
val columns: Array<String> = arrayOf( "x", "y", "b" )
|
||||
db.query("t", columns, null, null, null, null, null, null).use {
|
||||
assert(it.moveToFirst())
|
||||
assert(it.getType(0) == Cursor.FIELD_TYPE_INTEGER)
|
||||
assert(it.getType(1) == Cursor.FIELD_TYPE_INTEGER)
|
||||
assert(it.getType(2) == Cursor.FIELD_TYPE_BLOB)
|
||||
processTile(it, repo, level)
|
||||
while(it.moveToNext()) {
|
||||
processTile(it, repo, level)
|
||||
}
|
||||
}
|
||||
|
||||
db.close()
|
||||
}
|
||||
|
||||
private fun processTile(it: Cursor, repo: TileRepository, level: Int) {
|
||||
val x = it.getInt(0)
|
||||
val y = it.getInt(1)
|
||||
val blob = it.getBlob(2)
|
||||
val base64 = blob.toBase64()
|
||||
val tile = Tile(x, y, level, base64)
|
||||
val checkedTile = repo.getTile(x, y, level)
|
||||
if (checkedTile == null)
|
||||
repo.pushTile(tile)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue