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

commonMain.maryk.yaml.SelectReader.kt Maven / Gradle / Ivy

Go to download

Maryk is a Kotlin Multiplatform library which helps you to store, query and send data in a structured way over multiple platforms. The data store stores any value with a version, so it is possible to request only the changed data or live listen for updates.

There is a newer version: 0.6.0
Show newest version
package maryk.yaml

import maryk.json.ExceptionWhileReadingJson
import maryk.json.JsonToken
import maryk.json.TokenType
import maryk.lib.extensions.isSpacing
import maryk.yaml.PlainStyleMode.NORMAL

/**
 * Reads until is clear what is next token, selects relevant reader and continues reading.
 * Add [tag] for found tags, [extraIndent] on extra indent where it started reading.
 * Use [jsonTokenCreator] to create found tokens with which is relevant for maps where there also could be created fields
 * instead of values.
 * Set [startsAtNewLine] to true if it was started on a new line.
 */
internal fun IsYamlCharWithIndentsReader.selectReaderAndRead(
    startsAtNewLine: Boolean,
    tag: TokenType?,
    extraIndent: Int,
    jsonTokenCreator: JsonTokenCreator
): JsonToken {
    var indents = extraIndent
    // count white space
    while (this.lastChar.isSpacing()) {
        indents++
        read()
    }

    return when (this.lastChar) {
        '\n', '\r' -> {
            read()
            val indentCount = this.yamlReader.skipEmptyLinesAndCommentsAndCountIndents()
            val currentIndentCount = this.indentCount()
            when {
                indentCount < currentIndentCount -> return this.endIndentLevel(indentCount, tag, null)
                indentCount == currentIndentCount -> return this.continueIndentLevel(0, tag)
                else -> this.selectReaderAndRead(true, tag, indentCount - currentIndentCount, jsonTokenCreator)
            }
        }
        '\'' -> this.singleQuoteString(tag, indents, jsonTokenCreator)
        '\"' -> this.doubleQuoteString(tag, indents, jsonTokenCreator)
        '[' -> this.flowSequenceReader(tag, 1)
        '{' -> this.flowMapReader(tag, 1)
        ',' -> throw InvalidYamlContent("Invalid char $lastChar at this position")
        '|' -> {
            read()
            return LiteralStringReader(
                this.yamlReader,
                this
            ) {
                jsonTokenCreator(it, false, tag, 0)
            }.let {
                this.currentReader = it
                it.readUntilToken(0)
            }
        }
        '>' -> {
            read()
            return FoldedStringReader(
                this.yamlReader,
                this
            ) {
                jsonTokenCreator(it, false, tag, 0)
            }.let {
                this.currentReader = it
                it.readUntilToken(0)
            }
        }
        '!' -> this.tagReader { this.selectReaderAndRead(true, it, indents, jsonTokenCreator) }
        '&' -> this.anchorReader { this.selectReaderAndRead(true, tag, indents, jsonTokenCreator) }
        '*' -> this.aliasReader(NORMAL)
        '@', '`' -> throw InvalidYamlContent("Reserved indicators for future use and not supported by this reader")
        '%' -> throw InvalidYamlContent("Directive % indicator not allowed in this position")
        ']' -> throw InvalidYamlContent("Invalid char $lastChar at this position")
        '-' -> {
            read()

            if (this.lastChar.isWhitespace()) {
                // Sequences can start at same level as map
                val mapCorrection = if (this is MapItemsReader<*> && !startsAtNewLine) -1 else 0
                SequenceItemsReader(
                    yamlReader = this.yamlReader,
                    parentReader = this,
                    indentToAdd = indents + mapCorrection
                ).let {
                    this.currentReader = it
                    it.readUntilToken(0, tag)
                }
            } else {
                this.plainStringReader("-", tag, NORMAL, indents, jsonTokenCreator)
            }
        }
        '?' -> {
            try {
                read()
            } catch (e: ExceptionWhileReadingJson) {
                this.currentReader = ExplicitMapKeyReader(
                    this.yamlReader,
                    MapItemsReader(
                        this.yamlReader,
                        this
                    )
                )
                throw e
            }
            // If it turns out to not be an explicit key make it a Plain String reader
            if (!this.lastChar.isWhitespace()) {
                return (this.currentReader as IsYamlCharWithIndentsReader).plainStringReader(
                    "?",
                    tag,
                    NORMAL,
                    indents,
                    jsonTokenCreator
                )
            }

            this.foundMap(tag, indents)?.let {
                this.currentReader = ExplicitMapKeyReader(
                    this.yamlReader,
                    this.currentReader as MapItemsReader<*>
                )
                return it
            }

            ExplicitMapKeyReader(
                this.yamlReader,
                this as MapItemsReader<*>
            ).let {
                this.currentReader = it
                it.readUntilToken(indents)
            }
        }
        ':' -> {
            read()
            if (this.lastChar.isWhitespace()) {
                this.foundMap(tag, indents)?.let {
                    this.yamlReader.pushToken(this.readUntilToken(0))
                    return it
                }
                this.readUntilToken(0)
            } else {
                plainStringReader(":", tag, NORMAL, 1, jsonTokenCreator)
            }
        }
        '#' -> {
            this.commentReader {
                this.readUntilToken(0, tag)
            }
        }
        else -> this.plainStringReader("", tag, NORMAL, indents, jsonTokenCreator)
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy