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

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

The newest version!
package com.sandinh.phputils

import scala.collection.mutable.ArrayBuffer
import java.lang.reflect.Modifier
import java.nio.charset.Charset

private class SerializeException(s: String) extends Exception

private class Stringifier {
  private val charset = Charset.forName("UTF-8")
  private val refs = ArrayBuffer.empty[Any]
  private var php64: Boolean = true
  def write(o: Object, _php64bit: Boolean = true): String = {
    val buffer = new StringBuffer()
    php64 = _php64bit
    stringifyObject(o, buffer)
    buffer.toString
  }

  private def stringifyObject(o: Any, buffer: StringBuffer, allowReference: Boolean = true) = {
    if (o == null) stringifyNull(buffer)
    else if (allowReference && stringifyReference(o, buffer)) true
    else o match {
      case s: String       => stringifyString(s, buffer)
      case s: Char         => stringifyCharacter(s, buffer)
      case s: Int          => stringifyInteger(s, buffer)
      case s: Short        => stringifyInteger(s.toInt, buffer)
      case s: Byte         => stringifyInteger(s.toInt, buffer)
      case s: Long         => stringifyLong(s, buffer)
      case s: Double       => stringifyDouble(s, buffer)
      case s: Float        => stringifyFloat(s, buffer)
      case s: Boolean      => stringifyBoolean(s, buffer)
      case s: Array[_]     => stringifyArray(s, buffer)
      case s: Map[_, _]    => stringifyMap(s, buffer)
      case s: Iterable[_]  => stringifyCollection(s, buffer)
      case s: Serializable => stringifySerializable(s, buffer)
      case _               => throw new SerializeException("Unable to stringify " + o.getClass.getName)
    }
    refs += o
  }

  private def stringifyReference(o: Any, buffer: StringBuffer): Boolean = {
    // Don't allow references for simple types
    if (o.isInstanceOf[Number] || o.isInstanceOf[Boolean] || o.isInstanceOf[String]) return false
    val index = refs.indexOf(o)
    if (index != -1) {
      buffer.append("R:").append(index + 1).append(";")
      true
    } else false
  }

  private def stringifyString(string: String, buffer: StringBuffer) {
    val decoded: String = decode(string, charset)
    buffer.append("s:").append(decoded.length).append(":\"").append(string).append("\";")
  }

  private def stringifyCharacter(value: Char, buffer: StringBuffer) {
    buffer.append("s:1:\"").append(value).append("\";")
  }

  private def stringifyNull(buffer: StringBuffer) {
    buffer.append("N;")
  }

  private def stringifyInteger(number: Int, buffer: StringBuffer) {
    buffer.append("i:").append(number).append(";")
  }

  private def stringifyLong(number: Long, buffer: StringBuffer) {
    if ((number >= Integer.MIN_VALUE) && (number <= Integer.MAX_VALUE)) buffer.append("i:")
    else if (php64) buffer.append("i:")
    else buffer.append("d:")
    buffer.append(number).append(";")
  }

  private def stringifyDouble(number: Double, buffer: StringBuffer) {
    buffer.append("d:").append(number).append(";")
  }

  private def stringifyFloat(number: Float, buffer: StringBuffer) {
    buffer.append("d:").append(number).append(";")
  }

  private def stringifyBoolean(value: Boolean, buffer: StringBuffer) {
    buffer.append("b:").append(if (value) 1 else 0).append(";")
  }

  private def stringifyCollection(collection: Iterable[_], buffer: StringBuffer) {
    refs += collection
    buffer.append("a:").append(collection.size).append(":{")
    val iterator = collection.iterator
    var index = 0
    while (iterator.hasNext) {
      stringifyObject(index, buffer, allowReference = false)
      refs.trimEnd(1)
      stringifyObject(iterator.next(), buffer)
      index += 1
    }
    buffer.append('}')
  }

  private def stringifyArray(array: Array[_], buffer: StringBuffer) {
    refs += array
    val size = array.length
    buffer.append("a:").append(size).append(":{")
    for (i <- 0 until size) {
      stringifyObject(i, buffer, allowReference = false)
      refs.trimEnd(1)
      stringifyObject(array(i), buffer)
    }
    buffer.append('}')
  }

  private def stringifyMap(map: Map[_, _], buffer: StringBuffer) {
    refs += map
    buffer.append("a:").append(map.size).append(":{")
    map.foreach(e => {
      stringifyObject(e._1, buffer, allowReference = false)
      refs.trimEnd(1)
      stringifyObject(e._2, buffer)
    })
    buffer.append('}')
  }

  private def stringifySerializable(o: Serializable, buffer: StringBuffer) {

    refs += o
    var c: Class[_] = o.getClass
    val className = c.getName.replace('.', '\\')
    buffer.append("O:").append(className.length()).append(":\"").append(className).append("\":")

    val fieldBuffer = new StringBuffer()
    var fieldCount = 0
    while (c != null) {
      val fields = c.getDeclaredFields
      for (i <- 0 until fields.length) {
        val field = fields(i)
        if (!Modifier.isStatic(field.getModifiers) || !Modifier.isVolatile(field.getModifiers))
          try {
            field.setAccessible(true)
            stringifyObject(field.getName, fieldBuffer)
            refs.trimEnd(1)
            stringifyObject(field.get(o), fieldBuffer)
            fieldCount += 1
          } catch {
            case e: Exception => println("unable stringify " + className)
          }
      }
      c = c.getSuperclass
    }
    buffer.append(fieldCount).append(":{").append(fieldBuffer).append("}")
  }
}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy