summaryrefslogtreecommitdiff
path: root/src/library/scalax/collection/generic/covartest/SequenceView.scala
blob: 09d5c0efa1da7b3759650b6647c4cd845211908e (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
/*                     __                                               *\
**     ________ ___   / /  ___     Scala API                            **
**    / __/ __// _ | / /  / _ |    (c) 2003-2008, LAMP/EPFL             **
**  __\ \/ /__/ __ |/ /__/ __ |    http://scala-lang.org/               **
** /____/\___/_/ |_/____/_/ | |                                         **
**                          |/                                          **
\*                                                                      */

// $Id: Sequence.scala 16092 2008-09-12 10:37:06Z nielsen $


package scalax.collection.generic.covartest

import util.control.Break._
import annotation.unchecked.uncheckedVariance

import Sequence._

/** A non-strict projection of an iterable.
 * @author Sean McDirmid
 * @author Martin Odersky
 * @note this should really be a virtual class of SequenceFactory
 */
trait SequenceView[+UC[+B] <: Sequence[B], +A] extends IterableView[UC, A] with Sequence[A] {
self =>

  /** refined from Iterable.View */
  val origin: Sequence[_]

  trait Transformed[+B] extends SequenceView[UC, B] {
    val origin = self
    protected def asCC = asInstanceOf[SequenceView[UC, B]]
  }

  class Appended[+B >: A](that: Sequence[B]) extends Transformed[B] {
    override def elements: Iterator[B] = self.elements ++ that.elements
    override def length: Int = self.length + that.length
    override def apply(idx: Int): B = {
      val ll = self.length
      if (idx < ll) self.apply(idx) else that.apply(idx - ll)
    }
    override def stringPrefix = self.stringPrefix + "A"
  }

  class Sliced(from: Int, to: Int) extends Transformed[A] {
    override def elements: Iterator[A] = self.elements slice (from, to)
    override lazy val length: Int = ((to min self.length) - (from max 0) min 0)
    override def apply(idx: Int): A =
      if (idx >= 0 && idx < length) self.apply(idx + from)
      else throw new IndexOutOfBoundsException(idx.toString)
    override def stringPrefix = self.stringPrefix + "S"
    override def slice(from1: Int, to1: Int) =
      new self.Sliced(from + (from1 min length max 0) , to + (to1 min length max 0)).asInstanceOf[SequenceView[UC, A]]
  }

  class Mapped[+B](f: A => B) extends Transformed[B] {
    override def elements: Iterator[B] = self.elements map f
    override def length: Int = self.length
    override def apply(idx: Int): B = f(self.apply(idx))
    override def stringPrefix = self.stringPrefix + "M"
  }

  class Reversed extends Transformed[A] {
    override def elements: Iterator[A] = self.reversedElements
    override def length: Int = self.length
    override def apply(idx: Int): A = self.apply(length - 1 - idx)
    override def stringPrefix = super.stringPrefix+"R"
  }

  class Patched[+B >: A](from: Int, patch: Sequence[B], replaced: Int) extends Transformed[B] {
    val plen = patch.length
    override def elements: Iterator[B] = self.elements patch (from, patch, replaced)
    override def length: Int = self.length + plen - replaced
    override def apply(idx: Int): B =
      if (idx < from) self.apply(idx)
      else if (idx < from + plen) patch.apply(idx - from)
      else self.apply(idx - plen + replaced)
    override def stringPrefix = super.stringPrefix+"P"
  }

  class Zipped[+B](that: Sequence[B]) extends Transformed[(A, B)] {
    override def elements: Iterator[(A, B)] = self.elements zip that.elements
    override def length = self.length min that.length
    override def apply(idx: Int): (A, B) = (self.apply(idx), that.apply(idx))
    override def stringPrefix = super.stringPrefix+"Z"
  }

  override def ++[B >: A](that: Iterable[B]): SequenceView[UC, B] =
    new Appended[B](that.toSequence).asCC
  override def ++[B >: A](that: Iterator[B]): SequenceView[UC, B] =
    new Appended[B](that.toSequence).asCC
  override def map[B](f: A => B): SequenceView[UC, B] =
    new Mapped(f).asCC
  override def reverse: SequenceView[UC, A] =
    (new Reversed).asCC
  def patch[B >: A](from: Int, patch: Sequence[B], replaced: Int): SequenceView[UC, B] =
    if (0 <= from && from < length) new Patched(from, patch, replaced).asCC
    else throw new IndexOutOfBoundsException(from.toString)
  override def padTo[B >: A](len: Int, elem: B): SequenceView[UC, B] =
    patch(length, fill((len - length) max 0, elem), 0)
  override def zip[B](that: Iterable[B]): SequenceView[UC, (A, B)] =
    new Zipped(that.toSequence).asCC
  override def zipWithIndex: SequenceView[UC, (A, Int)] =
    zip((0 until length).asInstanceOf[Null]) // !@!
    /*
  override def zipAll[B, A1 >: A, B1 >: B](that: Iterable[B], thisElem: A1, thatElem: B1): SequenceView[UC, (A1, B1)] = {
    val that1 = that.toSequence
    self.padTo(that1.length, thisElem) zip that1.padTo(this.length, thatElem)//.asInstanceOf[SequenceView[UC, (A1, B1)]]
  }*/
  override def take(n: Int): SequenceView[UC, A] =
    slice(0, n)
  override def drop(n: Int): SequenceView[UC, A] =
    slice(n, Math.MAX_INT)
  override def splitAt(n: Int): (SequenceView[UC, A], SequenceView[UC, A]) = (take(n), drop(n))
  override def slice(from: Int, until: Int): SequenceView[UC, A] =
    new Sliced(from, until).asCC
  override def takeWhile(p: A => Boolean): SequenceView[UC, A] =
    take(prefixLength(p))
  override def dropWhile(p: A => Boolean): SequenceView[UC, A] =
    drop(prefixLength(p))
  override def span(p: A => Boolean): (SequenceView[UC, A], SequenceView[UC, A]) = {
    val n = prefixLength(p)
    (take(n), drop(n))
  }

  // missing here because we can't do anything about them, so we fall back to default construction
  // if an IterableView via newView: flatMap, filter, partition
}