Skip to content

Commit

Permalink
Have ArrayCharSequence reuse its Array.
Browse files Browse the repository at this point in the history
Your know, for performance.  Closes SI-5641.
  • Loading branch information
paulp committed May 5, 2012
1 parent 0fb12fa commit b5e9e4b
Show file tree
Hide file tree
Showing 3 changed files with 295 additions and 5 deletions.
25 changes: 20 additions & 5 deletions src/library/scala/runtime/SeqCharSequence.scala
Expand Up @@ -17,9 +17,24 @@ final class SeqCharSequence(val xs: collection.IndexedSeq[Char]) extends CharSeq
override def toString = xs.mkString("")
}

final class ArrayCharSequence(val xs: Array[Char]) extends CharSequence {
def length: Int = xs.length
def charAt(index: Int): Char = xs(index)
def subSequence(start: Int, end: Int): CharSequence = new ArrayCharSequence(copyOfRange(xs, math.max(0, start), math.min(xs.length, end)))
override def toString = xs.mkString("")
final class ArrayCharSequence(val xs: Array[Char], start: Int, end: Int) extends CharSequence {
def this(xs: Array[Char]) = this(xs, 0, xs.length)

def length: Int = math.max(0, end - start)
def charAt(index: Int): Char = {
if (0 <= index && index < length)
xs(start + index)
else throw new ArrayIndexOutOfBoundsException(index)
}
def subSequence(start0: Int, end0: Int): CharSequence = {
if (start0 < 0) throw new ArrayIndexOutOfBoundsException(start0)
else if (end0 > length) throw new ArrayIndexOutOfBoundsException(end0)
else if (end0 <= start0) new ArrayCharSequence(xs, 0, 0)
else {
val newlen = end0 - start0
val start1 = start + start0
new ArrayCharSequence(xs, start1, start1 + newlen)
}
}
override def toString = xs drop start take length mkString ""
}
248 changes: 248 additions & 0 deletions test/files/run/array-charSeq.check
@@ -0,0 +1,248 @@

[check 'abcdefghi'] len = 9
sub(0, 9) == 'abcdefghi'
sub(0, 0) == ''
sub(1, 9) == 'bcdefghi'
sub(0, 1) == 'a'
sub(2, 9) == 'cdefghi'
sub(0, 2) == 'ab'
sub(3, 9) == 'defghi'
sub(0, 3) == 'abc'
sub(4, 9) == 'efghi'
sub(0, 4) == 'abcd'
sub(5, 9) == 'fghi'
sub(0, 5) == 'abcde'
sub(6, 9) == 'ghi'
sub(0, 6) == 'abcdef'
sub(7, 9) == 'hi'
sub(0, 7) == 'abcdefg'
sub(8, 9) == 'i'
sub(0, 8) == 'abcdefgh'

[check 'bcdefgh'] len = 7
sub(0, 7) == 'bcdefgh'
sub(0, 0) == ''
sub(1, 7) == 'cdefgh'
sub(0, 1) == 'b'
sub(2, 7) == 'defgh'
sub(0, 2) == 'bc'
sub(3, 7) == 'efgh'
sub(0, 3) == 'bcd'
sub(4, 7) == 'fgh'
sub(0, 4) == 'bcde'
sub(5, 7) == 'gh'
sub(0, 5) == 'bcdef'
sub(6, 7) == 'h'
sub(0, 6) == 'bcdefg'

[check 'cdefg'] len = 5
sub(0, 5) == 'cdefg'
sub(0, 0) == ''
sub(1, 5) == 'defg'
sub(0, 1) == 'c'
sub(2, 5) == 'efg'
sub(0, 2) == 'cd'
sub(3, 5) == 'fg'
sub(0, 3) == 'cde'
sub(4, 5) == 'g'
sub(0, 4) == 'cdef'

[check 'def'] len = 3
sub(0, 3) == 'def'
sub(0, 0) == ''
sub(1, 3) == 'ef'
sub(0, 1) == 'd'
sub(2, 3) == 'f'
sub(0, 2) == 'de'

[check 'e'] len = 1
sub(0, 1) == 'e'
sub(0, 0) == ''

[check 'abcdefgh'] len = 8
sub(0, 8) == 'abcdefgh'
sub(0, 0) == ''
sub(1, 8) == 'bcdefgh'
sub(0, 1) == 'a'
sub(2, 8) == 'cdefgh'
sub(0, 2) == 'ab'
sub(3, 8) == 'defgh'
sub(0, 3) == 'abc'
sub(4, 8) == 'efgh'
sub(0, 4) == 'abcd'
sub(5, 8) == 'fgh'
sub(0, 5) == 'abcde'
sub(6, 8) == 'gh'
sub(0, 6) == 'abcdef'
sub(7, 8) == 'h'
sub(0, 7) == 'abcdefg'

[check 'bcdefg'] len = 6
sub(0, 6) == 'bcdefg'
sub(0, 0) == ''
sub(1, 6) == 'cdefg'
sub(0, 1) == 'b'
sub(2, 6) == 'defg'
sub(0, 2) == 'bc'
sub(3, 6) == 'efg'
sub(0, 3) == 'bcd'
sub(4, 6) == 'fg'
sub(0, 4) == 'bcde'
sub(5, 6) == 'g'
sub(0, 5) == 'bcdef'

[check 'cdef'] len = 4
sub(0, 4) == 'cdef'
sub(0, 0) == ''
sub(1, 4) == 'def'
sub(0, 1) == 'c'
sub(2, 4) == 'ef'
sub(0, 2) == 'cd'
sub(3, 4) == 'f'
sub(0, 3) == 'cde'

[check 'de'] len = 2
sub(0, 2) == 'de'
sub(0, 0) == ''
sub(1, 2) == 'e'
sub(0, 1) == 'd'

[check ''] len = 0

[check 'abcdefg'] len = 7
sub(0, 7) == 'abcdefg'
sub(0, 0) == ''
sub(1, 7) == 'bcdefg'
sub(0, 1) == 'a'
sub(2, 7) == 'cdefg'
sub(0, 2) == 'ab'
sub(3, 7) == 'defg'
sub(0, 3) == 'abc'
sub(4, 7) == 'efg'
sub(0, 4) == 'abcd'
sub(5, 7) == 'fg'
sub(0, 5) == 'abcde'
sub(6, 7) == 'g'
sub(0, 6) == 'abcdef'

[check 'bcdef'] len = 5
sub(0, 5) == 'bcdef'
sub(0, 0) == ''
sub(1, 5) == 'cdef'
sub(0, 1) == 'b'
sub(2, 5) == 'def'
sub(0, 2) == 'bc'
sub(3, 5) == 'ef'
sub(0, 3) == 'bcd'
sub(4, 5) == 'f'
sub(0, 4) == 'bcde'

[check 'cde'] len = 3
sub(0, 3) == 'cde'
sub(0, 0) == ''
sub(1, 3) == 'de'
sub(0, 1) == 'c'
sub(2, 3) == 'e'
sub(0, 2) == 'cd'

[check 'd'] len = 1
sub(0, 1) == 'd'
sub(0, 0) == ''

[check 'abcdef'] len = 6
sub(0, 6) == 'abcdef'
sub(0, 0) == ''
sub(1, 6) == 'bcdef'
sub(0, 1) == 'a'
sub(2, 6) == 'cdef'
sub(0, 2) == 'ab'
sub(3, 6) == 'def'
sub(0, 3) == 'abc'
sub(4, 6) == 'ef'
sub(0, 4) == 'abcd'
sub(5, 6) == 'f'
sub(0, 5) == 'abcde'

[check 'bcde'] len = 4
sub(0, 4) == 'bcde'
sub(0, 0) == ''
sub(1, 4) == 'cde'
sub(0, 1) == 'b'
sub(2, 4) == 'de'
sub(0, 2) == 'bc'
sub(3, 4) == 'e'
sub(0, 3) == 'bcd'

[check 'cd'] len = 2
sub(0, 2) == 'cd'
sub(0, 0) == ''
sub(1, 2) == 'd'
sub(0, 1) == 'c'

[check ''] len = 0

[check 'abcde'] len = 5
sub(0, 5) == 'abcde'
sub(0, 0) == ''
sub(1, 5) == 'bcde'
sub(0, 1) == 'a'
sub(2, 5) == 'cde'
sub(0, 2) == 'ab'
sub(3, 5) == 'de'
sub(0, 3) == 'abc'
sub(4, 5) == 'e'
sub(0, 4) == 'abcd'

[check 'bcd'] len = 3
sub(0, 3) == 'bcd'
sub(0, 0) == ''
sub(1, 3) == 'cd'
sub(0, 1) == 'b'
sub(2, 3) == 'd'
sub(0, 2) == 'bc'

[check 'c'] len = 1
sub(0, 1) == 'c'
sub(0, 0) == ''

[check 'abcd'] len = 4
sub(0, 4) == 'abcd'
sub(0, 0) == ''
sub(1, 4) == 'bcd'
sub(0, 1) == 'a'
sub(2, 4) == 'cd'
sub(0, 2) == 'ab'
sub(3, 4) == 'd'
sub(0, 3) == 'abc'

[check 'bc'] len = 2
sub(0, 2) == 'bc'
sub(0, 0) == ''
sub(1, 2) == 'c'
sub(0, 1) == 'b'

[check ''] len = 0

[check 'abc'] len = 3
sub(0, 3) == 'abc'
sub(0, 0) == ''
sub(1, 3) == 'bc'
sub(0, 1) == 'a'
sub(2, 3) == 'c'
sub(0, 2) == 'ab'

[check 'b'] len = 1
sub(0, 1) == 'b'
sub(0, 0) == ''

[check 'ab'] len = 2
sub(0, 2) == 'ab'
sub(0, 0) == ''
sub(1, 2) == 'b'
sub(0, 1) == 'a'

[check ''] len = 0

[check 'a'] len = 1
sub(0, 1) == 'a'
sub(0, 0) == ''
27 changes: 27 additions & 0 deletions test/files/run/array-charSeq.scala
@@ -0,0 +1,27 @@
object Test {
val arr = Array[Char]('a' to 'i': _*)
var xs: CharSequence = arr
val hash = xs.hashCode

def check(chars: CharSequence) {
println("\n[check '" + chars + "'] len = " + chars.length)
chars match {
case x: runtime.ArrayCharSequence => assert(x.xs eq arr, ((x.xs, arr)))
case x => assert(false, x)
}

0 until chars.length foreach { i =>
println("sub(%s, %s) == '%s'".format(i, chars.length, chars.subSequence(i, chars.length)))
println("sub(%s, %s) == '%s'".format(0, i, chars.subSequence(0, i)))
}
if (chars.length >= 2)
check(chars.subSequence(1, chars.length - 1))
}

def main(args: Array[String]): Unit = {
while (xs.length > 0) {
check(xs)
xs = xs.subSequence(0, xs.length - 1)
}
}
}

0 comments on commit b5e9e4b

Please sign in to comment.