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

com.sandinh.phputils.Parser.scala Maven / Gradle / Ivy

The newest version!
package com.sandinh.phputils

import scala.collection.mutable.ArrayBuffer
import java.nio.charset.Charset
import scala.util.Try

private class UnserializeException(s: String) extends Exception

private class Parser(str: String) {

  private var data = ""
  private var pos: Int = 0

  private val refs = ArrayBuffer.empty[Any]
  private val charset = Charset.forName("UTF-8")

  def parse(): Any = {
    data = decode(str, charset)
    val result = data.charAt(pos) match {
      case 's' => parseString()
      case 'i' =>
        val currentPos = pos
        Try(parseInteger()).getOrElse {
          pos = currentPos
          parseLong()
        }
      case 'd' => parseDouble()
      case 'b' => parseBoolean()
      case 'N' => parseNull()
      case 'a' => return parseArray()
      case 'R' => parseReference()
      case 'O' => parseObject()
      case _   => throw new UnserializeException("Unable to parse unknown type ")
    }
    refs += result
    result
  }

  private def parseString(): String = {
    val end = data.indexOf(':', pos + 2)
    val length = data.substring(pos + 2, end).toInt
    val raw = data.substring(end + 2, end + 2 + length)
    pos = end + length + 4
    encode(raw, charset)
  }

  private def parseInteger(): Int = {
    val end = data.indexOf(';', pos + 2)
    val result = data.substring(pos + 2, end).toInt
    pos = end + 1
    result
  }

  private def parseLong(): Long = {
    val end = data.indexOf(';', pos + 2)
    val result = data.substring(pos + 2, end).toLong
    pos = end + 1
    result
  }

  private def parseDouble(): Double = {
    val end = data.indexOf(';', pos + 2)
    val result = data.substring(pos + 2, end).toDouble
    pos = end + 1
    result
  }

  private def parseReference(): Any = {
    val end = data.indexOf(';', pos + 2)
    val index = data.substring(pos + 2, end).toInt
    pos = end + 1
    refs(index - 1)
  }

  private def parseBoolean(): Boolean = {
    val result = data.charAt(pos + 2) == '1'
    pos += 4
    result
  }

  private def parseNull(): Null = {
    pos += 2
    null
  }

  private def parseArray(): Map[Any, Any] = {
    val end = data.indexOf(':', pos + 2)
    val size = data.substring(pos + 2, end).toInt
    pos = end + 2
    var map = Map.empty[Any, Any]
    refs += map
    for (i <- 0 until size) {
      val key = parse()
      refs.trimEnd(1)
      val value = parse()
      map += key -> value
    }
    pos += 1
    map
  }

  def parseObject(): (String, Map[String, Any]) = {
    val startName = data.indexOf(':', pos + 2)
    val nameLength = data.substring(pos + 2, startName).toInt
    val endName = startName + 2 + nameLength
    val className = data.substring(startName + 2, endName)
    val startField = data.indexOf(":", endName + 2)
    val fieldCount = data.substring(endName + 2, startField).toInt
    pos = startField + 2
    var map = Map.empty[String, Any]
    refs += map
    for (i <- 0 until fieldCount) {
      val key = parseString()
      refs.trimEnd(1)
      val value = parse()
      map += key -> value
    }
    pos += 1
    (className, map)
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy