commonMain.ru.casperix.file_data.FileDataLoader.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of spine-jvm Show documentation
Show all versions of spine-jvm Show documentation
Signals for all occasions
package ru.casperix.file_data
import ru.casperix.misc.Left
import ru.casperix.misc.Right
import ru.casperix.multiplatform.loader.ResourceLoadError
import ru.casperix.multiplatform.loader.resourceLoader
import ru.casperix.signals.concrete.EitherFuture
import ru.casperix.signals.concrete.map
object FileDataLoader {
class InvalidFileData(val path: String, val message: String) : ResourceLoadError
fun load(path: String): EitherFuture {
return resourceLoader.loadText(path).map({
try {
Right(parse(it))
} catch (e: Throwable) {
Left(InvalidFileData(path, e.message ?: ""))
}
}, {
it
})
}
private fun parse(raw: String): FileData {
val lines = raw.replace("\r\n", "\n").replace("\r", "\n").split("\n")
val stream = lines.toMutableList()
val fileData = FileData()
var currentPage = PageData()
var currentBlock: BlockData? = null
fileData.pageList += currentPage
while (true) {
val next = stream.removeFirstOrNull() ?: return fileData
val firstChar = next.firstOrNull()
if (firstChar == null) {
// next page
currentPage = PageData()
fileData.pageList += currentPage
} else if (!firstChar.isWhitespace()) {
// next block
currentBlock = BlockData(next)
currentPage.blockList += currentBlock
} else {
if (currentBlock == null) {
println("Invalid name-value place: \"$next\"")
continue
}
// next name-value
val parts = Regex("\\s*(\\w+)\\s*:\\s*(.+)").findAll(next).toList().flatMap {
it.groupValues
}
val name = parts.getOrNull(1)
val value = parts.getOrNull(2)
if (name != null && value != null) {
currentBlock.values[name] = value
} else {
println("Cant parse line: \"$next\"")
continue
}
}
}
}
}