Created
July 27, 2015 22:38
-
-
Save sirthias/88be2871d363f023c237 to your computer and use it in GitHub Desktop.
Comparison of Vector-based and Array-based basic JValue ASTs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.json4s.basic.ast | |
import scala.annotation.tailrec | |
import scala.collection.immutable.VectorBuilder | |
/** | |
* Minimal AST for " The JavaScript Object Notation (JSON) Data Interchange Format" | |
* RFC 7159 (https://tools.ietf.org/html/rfc7159) | |
*/ | |
sealed abstract class JValue extends Serializable with Product | |
case object JNull extends JValue | |
sealed abstract class JBoolean extends JValue { | |
def isEmpty = false | |
def get: Boolean | |
} | |
object JBoolean { | |
def apply(x: Boolean): JBoolean = if (x) JTrue else JFalse | |
} | |
case object JTrue extends JBoolean { | |
def get = true | |
} | |
case object JFalse extends JBoolean { | |
def get = false | |
} | |
final case class JString(value: String) extends JValue | |
/** | |
* Contract: `value` *must* be formatted according to https://tools.ietf.org/html/rfc7159#section-6 | |
*/ | |
final case class JNumber(value: String) extends JValue | |
object JNumber { | |
def apply(value: Byte): JNumber = JNumber(value.toString) | |
def apply(value: Short): JNumber = JNumber(value.toString) | |
def apply(value: Int): JNumber = JNumber(value.toString) | |
def apply(value: Long): JNumber = JNumber(value.toString) | |
def apply(value: Float): JNumber = JNumber(value.toString) | |
def apply(value: Double): JNumber = JNumber(value.toString) | |
def apply(value: BigInt): JNumber = JNumber(value.toString) | |
def apply(value: BigDecimal): JNumber = JNumber(value.toString) | |
} | |
sealed abstract class JContainer[T <: AnyRef] extends JValue { | |
def value: Vector[T] = { | |
val array = underlyingArray_unsafe | |
val vb = new VectorBuilder[T] | |
@tailrec def copyFrom(ix: Int): Vector[T] = | |
if (ix < array.length) { | |
vb += array(ix) | |
copyFrom(ix + 1) | |
} else vb.result() | |
copyFrom(0) | |
} | |
def isEmpty = false | |
def get: Vector[T] = value | |
def underlyingArray_unsafe: Array[T] | |
def productArity = 1 | |
def productElement(n: Int): Any = | |
if (n == 0) value else throw new IndexOutOfBoundsException(s"Expected 0, was $n") | |
override def equals(obj: Any): Boolean = | |
obj match { | |
case x: JContainer[_] ⇒ | |
canEqual(obj) && java.util.Arrays.equals(underlyingArray_unsafe.asInstanceOf[Array[Object]], | |
x.underlyingArray_unsafe.asInstanceOf[Array[Object]]) | |
case _ ⇒ false | |
} | |
override def hashCode(): Int = java.util.Arrays.hashCode(underlyingArray_unsafe.asInstanceOf[Array[Object]]) | |
} | |
sealed abstract class JObject extends JContainer[JField] { | |
override def productPrefix = "JObject" | |
def canEqual(that: Any): Boolean = that.isInstanceOf[JObject] | |
} | |
object JObject { | |
def apply(fields: JField*): JObject = create_unsafe(fields.toArray) | |
def apply(fields: Vector[JField]): JObject = create_unsafe(fields.toArray) | |
def apply(fields: Array[JField]): JObject = JObject(fields, 0, fields.length) | |
def apply(fields: Array[JField], start: Int, end: Int): JObject = { | |
val len = end - start | |
if (len < 0) throw new IllegalArgumentException(s"$start > $end") | |
val slice = new Array[JField](len) | |
System.arraycopy(fields, start, slice, 0, math.min(fields.length - start, len)) | |
create_unsafe(slice) | |
} | |
def create_unsafe(_fields: Array[JField]): JObject = | |
new JObject { | |
def underlyingArray_unsafe = _fields | |
} | |
def unapply(obj: JObject): JObject = obj | |
} | |
final case class JField(key: String, value: JValue) | |
sealed abstract class JArray extends JContainer[JValue] { | |
override def productPrefix = "JArray" | |
def canEqual(that: Any): Boolean = that.isInstanceOf[JArray] | |
} | |
object JArray { | |
def apply(elements: JValue*): JArray = create_unsafe(elements.toArray) | |
def apply(elements: Vector[JValue]): JArray = create_unsafe(elements.toArray) | |
def apply(elements: Array[JValue]): JArray = JArray(elements, 0, elements.length) | |
def apply(elements: Array[JValue], start: Int, end: Int): JArray = { | |
val len = end - start | |
if (len < 0) throw new IllegalArgumentException(s"$start > $end") | |
val slice = new Array[JValue](len) | |
System.arraycopy(elements, start, slice, 0, math.min(elements.length - start, len)) | |
create_unsafe(slice) | |
} | |
def create_unsafe(_elements: Array[JValue]): JArray = | |
new JArray { | |
def underlyingArray_unsafe = _elements | |
} | |
def unapply(obj: JArray): JArray = obj | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.json4s.basic.ast | |
/** | |
* Minimal AST for " The JavaScript Object Notation (JSON) Data Interchange Format" | |
* RFC 7159 (https://tools.ietf.org/html/rfc7159) | |
*/ | |
sealed abstract class JValue extends Serializable with Product | |
case object JNull extends JValue | |
sealed abstract class JBoolean extends JValue { | |
def isEmpty = false | |
def get: Boolean = value | |
def value: Boolean | |
} | |
object JBoolean { | |
def apply(x: Boolean): JBoolean = if (x) JTrue else JFalse | |
} | |
case object JTrue extends JBoolean { | |
def value = true | |
} | |
case object JFalse extends JBoolean { | |
def value = false | |
} | |
final case class JString(value: String) extends JValue | |
/** | |
* Contract: `value` *must* be formatted according to https://tools.ietf.org/html/rfc7159#section-6 | |
*/ | |
final case class JNumber(value: String) extends JValue | |
object JNumber { | |
def apply(value: Byte): JNumber = JNumber(value.toString) | |
def apply(value: Short): JNumber = JNumber(value.toString) | |
def apply(value: Int): JNumber = JNumber(value.toString) | |
def apply(value: Long): JNumber = JNumber(value.toString) | |
def apply(value: Float): JNumber = JNumber(value.toString) | |
def apply(value: Double): JNumber = JNumber(value.toString) | |
def apply(value: BigInt): JNumber = JNumber(value.toString) | |
def apply(value: BigDecimal): JNumber = JNumber(value.toString) | |
} | |
final case class JObject(fields: Vector[JField]) extends JValue | |
final case class JField(key: String, value: JValue) | |
final case class JArray(elements: Vector[JValue]) extends JValue |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment