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

com.rojoma.json.v3.extensions.StringWriter.scala Maven / Gradle / Ivy

The newest version!
package com.rojoma.json.v3
package extensions

import scala.collection.JavaConverters._
import java.lang.reflect.InvocationTargetException
import java.util.ServiceLoader
import java.io.Writer

trait StringWriter {
  def toString(s: String): String
  def toWriter(w: Writer, s: String): Unit
}

private[extensions] class SimpleStringWriter extends StringWriter {
  def toString(s: String) = {
    val sw = new java.io.StringWriter
    toWriter(sw, s)
    sw.toString
  }

  def toWriter(output: Writer, s: String) {
    output.write('"')
    val fastEnd = gallop(s, 0)
    if(fastEnd == s.length) {
      output.write(s)
    } else {
      slowPath(s, fastEnd, output: Writer)
    }
    output.write('"')
  }

  def slowPath(s: String, endOfFastPrefix: Int, output: Writer) {
    if(endOfFastPrefix != 0) output.write(s, 0, endOfFastPrefix)
    var i = endOfFastPrefix
    val len = s.length
    do {
      val c = s.charAt(i)

      c match {
        case '"' => output.write("\\\"")
        case '\\' => output.write("\\\\")
        case '\b' => output.write("\\b")
        case '\f' => output.write("\\f")
        case '\n' => output.write("\\n")
        case '\r' => output.write("\\r")
        case '\t' => output.write("\\t")
        case _ if shouldEscape(c) => unicode(c, output)
        case _ if fastCopy(c) =>
          val end = gallop(s, i + 1)
          output.write(s, i, end - i)
          i = end - 1
        case _ =>
          output.write(c)
      }

      i += 1
    } while(i != len)
  }

  def gallop(s: String, start: Int): Int = {
    var i = start
    val end = s.length
    while(i != end && fastCopy(s.charAt(i))) i += 1
    i
  }

  def fastCopy(c: Char): Boolean = c >= ' ' && c <= '~' && c != '"' && c != '\\'

  def shouldEscape(c: Char): Boolean = {
    val t = Character.getType(c)
    (t == Character.SURROGATE) || (t == Character.CONTROL) || (t == Character.UNASSIGNED) || (t == Character.PRIVATE_USE) || (t == Character.LINE_SEPARATOR) || (t == Character.PARAGRAPH_SEPARATOR)
  }

  def unicode(c: Char, output: Writer) = output.write("\\u%04x".format(c.toInt))
}

object StringWriter {
  val stringWriter: StringWriter = {
    val serviceLoader = ServiceLoader.load(classOf[StringWriter])
    serviceLoader.iterator().asScala.toStream.headOption match {
      case None =>
        try {
          Class.forName("com.rojoma.json.v3.extensions.SimpleStringWriter").getConstructor().newInstance().asInstanceOf[StringWriter]
        } catch {
          case e: InvocationTargetException if e.getCause != null =>
            throw e.getCause
        }
      case Some(l) =>
        l
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy