/* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** \* */ // $Id: BoxedAnyArray.scala 18572 2009-08-25 14:14:11Z odersky $ package scala.runtime import scala.reflect.ClassManifest import compat.Platform /** * Arrays created by <code>new Array[T](length)</code> where <code>T</code> * is a type variable. * * @author Martin Odersky */ @serializable final class BoxedAnyArray[A](val length: Int) extends BoxedArray[A] { def elemManifest: ClassManifest[A] = null private var boxed = new Array[AnyRef](length) // private val hash = boxed.hashCode() private var unboxed: AnyRef = null private var elemClass: Class[_] = null def apply(index: Int): A = synchronized { if (unboxed eq null) boxed(index) else if (elemClass eq classOf[Int]) Int.box(unboxed.asInstanceOf[Array[Int]](index)) else if (elemClass eq classOf[Double]) Double.box(unboxed.asInstanceOf[Array[Double]](index)) else if (elemClass eq classOf[Float]) Float.box(unboxed.asInstanceOf[Array[Float]](index)) else if (elemClass eq classOf[Long]) Long.box(unboxed.asInstanceOf[Array[Long]](index)) else if (elemClass eq classOf[Char]) Char.box(unboxed.asInstanceOf[Array[Char]](index)) else if (elemClass eq classOf[Byte]) Byte.box(unboxed.asInstanceOf[Array[Byte]](index)) else if (elemClass eq classOf[Short]) Short.box(unboxed.asInstanceOf[Array[Short]](index)) else if (elemClass eq classOf[Boolean]) Boolean.box(unboxed.asInstanceOf[Array[Boolean]](index)) else unboxed.asInstanceOf[Array[AnyRef]](index) }.asInstanceOf[A] def update(index: Int, _elem: A): Unit = synchronized { val elem = _elem.asInstanceOf[AnyRef] if (unboxed eq null) boxed(index) = elem else if (elemClass eq classOf[Int]) unboxed.asInstanceOf[Array[Int]](index) = Int.unbox(elem) else if (elemClass eq classOf[Double]) unboxed.asInstanceOf[Array[Double]](index) = Double.unbox(elem) else if (elemClass eq classOf[Float]) unboxed.asInstanceOf[Array[Float]](index) = Float.unbox(elem) else if (elemClass eq classOf[Long]) unboxed.asInstanceOf[Array[Long]](index) = Long.unbox(elem) else if (elemClass eq classOf[Char]) unboxed.asInstanceOf[Array[Char]](index) = Char.unbox(elem) else if (elemClass eq classOf[Byte]) unboxed.asInstanceOf[Array[Byte]](index) = Byte.unbox(elem) else if (elemClass eq classOf[Short]) unboxed.asInstanceOf[Array[Short]](index) = Short.unbox(elem) else if (elemClass eq classOf[Boolean]) unboxed.asInstanceOf[Array[Boolean]](index) = Boolean.unbox(elem) else unboxed.asInstanceOf[Array[AnyRef]](index) = elem } def unbox(elemClass: Class[_]): AnyRef = synchronized { if (unboxed eq null) { this.elemClass = elemClass; if (elemClass eq classOf[Int]) { val newvalue = new Array[Int](length) var i = 0 while (i < length) { newvalue(i) = Int.unbox(boxed(i)) i += 1 } unboxed = newvalue } else if (elemClass eq classOf[Double]) { val newvalue = new Array[Double](length) var i = 0 while (i < length) { newvalue(i) = Double.unbox(boxed(i)) i += 1 } unboxed = newvalue; } else if (elemClass eq classOf[Float]) { val newvalue = new Array[Float](length) var i = 0 while (i < length) { newvalue(i) = Float.unbox(boxed(i)) i += 1 } unboxed = newvalue; } else if (elemClass eq classOf[Long]) { val newvalue = new Array[Long](length) var i = 0 while (i < length) { newvalue(i) = Long.unbox(boxed(i)) i += 1 } unboxed = newvalue; } else if (elemClass eq classOf[Char]) { val newvalue = new Array[Char](length) var i = 0 while (i < length) { newvalue(i) = Char.unbox(boxed(i)) i += 1 } unboxed = newvalue } else if (elemClass eq classOf[Byte]) { val newvalue = new Array[Byte](length) var i = 0 while (i < length) { newvalue(i) = Byte.unbox(boxed(i)) i += 1 } unboxed = newvalue; } else if (elemClass eq classOf[Short]) { val newvalue = new Array[Short](length) var i = 0 while (i < length) { newvalue(i) = Short.unbox(boxed(i)) i += 1 } unboxed = newvalue; } else if (elemClass eq classOf[Boolean]) { val newvalue = new Array[Boolean](length) var i = 0 while (i < length) { newvalue(i) = Boolean.unbox(boxed(i)) i += 1 } unboxed = newvalue; } else if (elemClass == classOf[AnyRef]) { unboxed = boxed } else { unboxed = Platform.createArray(elemClass, length) if (elemClass.isArray) { var i = 0 while (i < length) { boxed(i) match { case ba: BoxedArray[_] => boxed(i) = ba.unbox(elemClass.getComponentType()) case _ => } i += 1 } } Platform.arraycopy(boxed, 0, unboxed, 0, length) } boxed = null } unboxed } /* !!! todo: deal with array equality override def equals(other: Any): Boolean = other.isInstanceOf[BoxedAnyArray[_]] && (this eq (other.asInstanceOf[BoxedAnyArray[_]])) || (if (unboxed eq null) boxed == other else unboxed == other) override def hashCode(): Int = hash */ def value: AnyRef = { if (unboxed eq null) throw new NotDefinedError("BoxedAnyArray.value") unboxed } private def adapt(other: AnyRef): AnyRef = if (this.unboxed eq null) other match { case that: BoxedAnyArray[_] => if (that.unboxed eq null) { that.boxed } else { if (ScalaRunTime.isValueClass(that.elemClass)) unbox(that.elemClass); that.unboxed } case that: BoxedArray[_] => adapt(that.value) case that: Array[Int] => unbox(classOf[Int]); that case that: Array[Double] => unbox(classOf[Double]); that case that: Array[Float] => unbox(classOf[Float]); that case that: Array[Long] => unbox(classOf[Long]); that case that: Array[Char] => unbox(classOf[Char]); that case that: Array[Short] => unbox(classOf[Short]); that case that: Array[Byte] => unbox(classOf[Byte]); that case that: Array[Boolean] => unbox(classOf[Boolean]); that case _ => other } else other match { case that: BoxedAnyArray[_] => if (that.unboxed ne null) that.unboxed else if (ScalaRunTime.isValueClass(this.elemClass)) that.unbox(this.elemClass) else that.boxed case that: BoxedArray[_] => adapt(that.value) case _ => other } override def copyFrom(src: AnyRef, from: Int, to: Int, len: Int) { val src1 = adapt(src) Array.copy(src1, from, if (unboxed ne null) unboxed else boxed, to, len) } override def copyTo(from: Int, dest: AnyRef, to: Int, len: Int) { var dest1 = adapt(dest) Array.copy(if (unboxed ne null) unboxed else boxed, from, dest1, to, len) } }