implementations.StandardParser.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of fluid-json-basic Show documentation
Show all versions of fluid-json-basic Show documentation
A JSON library written in pure Kotlin (basic variant)
The newest version!
package com.github.fluidsonic.fluid.json
internal object StandardParser : JSONParser {
private fun parse(source: JSONReader, expectedType: ExpectedType, withTermination: Boolean) =
source.withTermination(withTermination) { parseUnterminated(source, expectedType) }
override fun parseValueOrNull(source: JSONReader, withTermination: Boolean) =
parse(source, ExpectedType.any, withTermination = withTermination)
override fun parseList(source: JSONReader, withTermination: Boolean) =
parse(source, ExpectedType.list, withTermination = withTermination) as List<*>
@Suppress("UNCHECKED_CAST")
override fun parseMap(source: JSONReader, withTermination: Boolean) =
parse(source, ExpectedType.map, withTermination = withTermination) as Map
@Suppress("UNCHECKED_CAST")
private fun parseUnterminated(source: JSONReader, expectedType: ExpectedType): Any? {
var currentList: MutableList? = null
var currentKey: String? = null
var currentMap: MutableMap? = null
val parents = mutableListOf()
val parentKeys = mutableListOf()
when (expectedType) {
ExpectedType.any -> Unit
ExpectedType.list -> source.nextToken == JSONToken.listStart ||
throw JSONException.Schema(
message = "Expected a list, got ${source.nextToken}",
offset = source.offset,
path = source.path
)
ExpectedType.map -> source.nextToken == JSONToken.mapStart ||
throw JSONException.Schema(
message = "Expected a map, got ${source.nextToken}",
offset = source.offset,
path = source.path
)
}
loop@ while (true) {
val value: Any? = when (source.nextToken) {
JSONToken.booleanValue ->
source.readBoolean()
JSONToken.listEnd -> {
source.readListEnd()
val list = currentList
val parentCount = parents.size
if (parentCount > 0) {
val parent = parents.removeAt(parentCount - 1)
if (parent is MutableList<*>) {
currentList = parent as MutableList
}
else {
currentList = null
currentMap = parent as MutableMap
}
}
else {
currentList = null
currentMap = null
}
list
}
JSONToken.listStart -> {
source.readListStart()
val list = mutableListOf()
if (currentList != null) {
parents += currentList
}
else if (currentMap != null) {
parents += currentMap
currentMap = null
}
currentList = list
continue@loop
}
JSONToken.nullValue
-> source.readNull()
JSONToken.mapEnd -> {
source.readMapEnd()
val map = currentMap
val parentCount = parents.size
if (parentCount > 0) {
val parent = parents.removeAt(parentCount - 1)
if (parent is MutableMap<*, *>) {
currentMap = parent as MutableMap
}
else {
currentList = parent as MutableList
currentMap = null
}
}
else {
currentList = null
currentMap = null
}
val parentKeyCount = parentKeys.size
if (parentKeyCount > 0) {
currentKey = parentKeys.removeAt(parentKeyCount - 1)
}
map
}
JSONToken.mapKey -> {
currentKey = source.readMapKey()
continue@loop
}
JSONToken.mapStart -> {
source.readMapStart()
val map = mutableMapOf()
if (currentMap != null) {
parents += currentMap
}
else if (currentList != null) {
parents += currentList
currentList = null
}
if (currentKey != null) {
parentKeys += currentKey
currentKey = null
}
currentMap = map
continue@loop
}
JSONToken.numberValue ->
source.readNumber()
JSONToken.stringValue ->
source.readString()
else ->
throw IllegalStateException("reader is messed up: ${source.nextToken}")
}
when {
currentList != null -> currentList.add(value)
currentMap != null -> currentMap[currentKey] = value
else -> return value
}
}
}
private enum class ExpectedType {
any, list, map
}
}