package scala.tools.nsc.doc.html.page import JSONFormat.format private[page] object JSONFormat { def format(x: Any): String = x match { case s: String => s"""\"${quoteString(s)}\"""" case jo: JSONObject => jo.toString case ja: JSONArray => ja.toString case other => throw new UnsupportedOperationException(s"Value $other of class ${other.getClass} cannot be formatted.") } /** This function can be used to properly quote Strings for JSON output. */ def quoteString(s: String): String = { val len: Int = s.length val buf = new StringBuilder(len + len/4) var i: Int = 0 while (i < len) { s.apply(i) match { case '"' => buf ++= "\\\"" case '\\' => buf ++= "\\\\" case '/' => buf ++= "\\/" case '\b' => buf ++= "\\b" case '\f' => buf ++= "\\f" case '\n' => buf ++= "\\n" case '\r' => buf ++= "\\r" case '\t' => buf ++= "\\t" /* We'll unicode escape any control characters. These include: * 0x00 -> 0x1f : ASCII Control (C0 Control Codes) * 0x7f : ASCII DELETE * 0x80 -> 0x9f : C1 Control Codes * * Per RFC4627, section 2.5, we're not technically required to * encode the C1 codes, but we do to be safe. */ case c if ((c >= '\u0000' && c <= '\u001f') || (c >= '\u007f' && c <= '\u009f')) => val cint = c.toInt buf ++= f"\\u$cint%04x" case c => buf += c } i += 1 } buf.toString() } } /** Represents a JSON Object (map). */ private[page] case class JSONObject(obj: Map[String,Any]) { override def toString = obj.map({ case (k,v) => format(k) + " : " + format(v) }).mkString("{", ", ", "}") } /** Represents a JSON Array (vector). */ private[page] case class JSONArray(vector: Vector[Any]) { override def toString = vector.map(format).mkString("[", ", ", "]") }