All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.ru.casperix.file_data.FileDataLoader.kt Maven / Gradle / Ivy

There is a newer version: 0.9.0
Show newest version
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 {
    private val cache = mutableMapOf>()

    data class InvalidFileData(val path: String, val message: String) : ResourceLoadError

    fun load(path: String): EitherFuture {
        return cache.getOrPut(path) {
            resourceLoader.loadText(path).map({
                try {
                    Right(parse(it))
                } catch (e: Throwable) {
                    Left(InvalidFileData(path, e.message ?: ""))
                }
            }, {
                it
            })
        }
    }

    fun parse(raw: String): FileData {
        val lineSplitter = Regex("(\\r\\n|\\r|\\n)")
        val nameValueTemplate = Regex("\\s*(\\w+)\\s*:\\s*(.+)")
        val titleTemplate = Regex("^[^:]*")

        val fileData = FileData()
        var currentPage = PageData()
        var currentBlock: BlockData? = null

        fileData.pageList += currentPage

        val lines = raw.split(lineSplitter)
        lines.forEachIndexed { index, line ->
            if (line.isEmpty()) {
                //  ignore last empty line
                if (index == lines.lastIndex) return@forEachIndexed

                //  next page
                currentPage = PageData()
                fileData.pageList += currentPage
            } else {
                val res1 = nameValueTemplate.matchEntire(line)
                if (res1 != null) {
                    //  next property
                    val name = res1.groupValues[1]
                    val value = res1.groupValues[2]
                    currentBlock!!.values[name] = value
                } else {
                    val res2 = titleTemplate.matchEntire(line)
                    if (res2 != null) {
                        //  next block
                        val title = res2.value
                        currentBlock = BlockData(title)
                        currentPage.blockList += currentBlock!!
                    } else {
                        throw Exception("Invalid file-data")
                    }
                }
            }
        }

        if (!fileData.pageList.contains(currentPage)) {
            fileData.pageList += currentPage
        }

        return fileData
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy