summaryrefslogtreecommitdiff
path: root/src/library/scalax/runtime/BoxedArray.scala
blob: 47bb3a0d6445c8ee6a4dc5fa1c1ae7dd49cad317 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/*                     __                                               *\
**     ________ ___   / /  ___     Scala API                            **
**    / __/ __// _ | / /  / _ |    (c) 2002-2009, LAMP/EPFL             **
**  __\ \/ /__/ __ |/ /__/ __ |    http://scala-lang.org/               **
** /____/\___/_/ |_/____/_/ | |                                         **
**                          |/                                          **
\*                                                                      */

// $Id: BoxedArray.scala 17000 2009-01-29 13:05:53Z odersky $


package scalax.runtime

import Predef._
import collection.mutable.{Vector, ArrayBuffer}
import collection.generic._

/**
 *  <p>A class representing <code>Array[T]</code></p>
 *
 *  @author  Martin Odersky, Stephane Micheloud
 *  @version 1.0
 */
abstract class BoxedArray[A] extends Vector[A] with MutableVectorTemplate[BoxedArray, A] with Boxed {

  /** The length of the array */
  def length: Int

  /** The element at given index */
  def apply(index: Int): A

  /** Update element at given index */
  def update(index: Int, elem: A): Unit

  /** Creates new builder for this collection ==> move to subclasses
   *
   * */
  def newBuilder[B] = new ArrayBuffer[B].mapResult[BoxedArray] { // !!! Adriaan: can't drop [BoxedArray] here
    _.toArray.asInstanceOf[BoxedArray[B]]
  }

  /** Convert to Java array.
   *  @param elemTag    Either one of the tags ".N" where N is the name of a primitive type
   *                    (@see ScalaRunTime), or a full class name.
   */
  def unbox(elemClass: Class[_]): AnyRef

  /** The underlying array value
   */
  def value: AnyRef

  def copyFrom(src: AnyRef, from: Int, to: Int, len: Int): Unit =
    Array.copy(src, from, value, to, len)

  def copyTo(from: Int, dest: AnyRef, to: Int, len: Int): Unit = {
    Array.copy(value, from, dest, to, len)
  }

  override def equals(other: Any) =
    (value == other) ||
    other.isInstanceOf[BoxedArray[_]] && (value == other.asInstanceOf[BoxedArray[_]].value)

  override def hashCode(): Int = value.hashCode()

  /** Fills the given array <code>xs</code> with the elements of
   *  this sequence starting at position <code>start</code>.
   *
   *  @param  xs the array to fill.
   *  @param  start starting index.
   *  @pre    the array must be large enough to hold all elements.
   */
  override def copyToArray[B](xs: Array[B], start: Int, len: Int): Unit =
    copyTo(0, xs, start, len)

  final def deepToString() = deepMkString(stringPrefix + "(", ", ", ")")

  final def deepMkString(start: String, sep: String, end: String): String = {
    def _deepToString(x: Any) = x match {
      case a: AnyRef if ScalaRunTime.isArray(a) =>
        ScalaRunTime.boxArray(a).deepMkString(start, sep, end)
      case _ =>
        ScalaRunTime.stringOf(x)
    }
    val buf = new StringBuilder()
    buf.append(start)
    val elems = elements
    if (elems.hasNext) buf.append(_deepToString(elems.next))
    while (elems.hasNext) {
      buf.append(sep); buf.append(_deepToString(elems.next))
    }
    buf.append(end)
    buf.toString
  }

  final def deepMkString(sep: String): String = this.deepMkString("", sep, "")

  final def deepEquals(that: Any): Boolean = {
    def _deepEquals(x1: Any, x2: Any) = (x1, x2) match {
      case (a1: BoxedArray[_], a2: BoxedArray[_]) =>
        _sameElements(a1, a2)
      case (a1: AnyRef, a2: AnyRef)
           if ScalaRunTime.isArray(a1) && ScalaRunTime.isArray(a2) =>
        _sameElements(ScalaRunTime.boxArray(a1), ScalaRunTime.boxArray(a2))
      case _ =>
        x1.equals(x2)
    }
    def _sameElements(a1: BoxedArray[_], a2: BoxedArray[_]): Boolean = {
      val it1 = a1.elements
      val it2 = a2.elements
      var res = true
      while (res && it1.hasNext && it2.hasNext)
        res = _deepEquals(it1.next, it2.next)
      !it1.hasNext && !it2.hasNext && res
    }
    that match {
      case a: BoxedArray[_] =>
        _sameElements(this, a)
      case a: AnyRef if ScalaRunTime.isArray(a) =>
        _sameElements(this, ScalaRunTime.boxArray(a))
      case _ =>
        false
    }
  }

  override final def stringPrefix: String = "Array"

  protected def countAndMemo(p: A => Boolean): (Int, Array[Boolean]) = {
    val len = length
    val memo = new Array[Boolean](len)
    var count = 0
    var i = 0
    while (i < len) {
      if (p(this(i))) { memo(i) = true; count += 1 }
      i += 1
    }
    (count, memo)
  }
}