diff options
author | Paul Phillips <paulp@improving.org> | 2012-05-04 02:22:51 -0700 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2012-05-04 18:24:16 -0700 |
commit | b5e9e4b9502f02c3de31d32b71f82ea1e6723f01 (patch) | |
tree | b6e1d9f4b394b79951f21c5bb980ace12d4fc8f7 | |
parent | 0fb12fa0620c5f9999e309a4de7831549b283c24 (diff) | |
download | scala-b5e9e4b9502f02c3de31d32b71f82ea1e6723f01.tar.gz scala-b5e9e4b9502f02c3de31d32b71f82ea1e6723f01.tar.bz2 scala-b5e9e4b9502f02c3de31d32b71f82ea1e6723f01.zip |
Have ArrayCharSequence reuse its Array.
Your know, for performance. Closes SI-5641.
-rw-r--r-- | src/library/scala/runtime/SeqCharSequence.scala | 25 | ||||
-rw-r--r-- | test/files/run/array-charSeq.check | 248 | ||||
-rw-r--r-- | test/files/run/array-charSeq.scala | 27 |
3 files changed, 295 insertions, 5 deletions
diff --git a/src/library/scala/runtime/SeqCharSequence.scala b/src/library/scala/runtime/SeqCharSequence.scala index 7f7bca789f..6bf88e0729 100644 --- a/src/library/scala/runtime/SeqCharSequence.scala +++ b/src/library/scala/runtime/SeqCharSequence.scala @@ -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 "" } diff --git a/test/files/run/array-charSeq.check b/test/files/run/array-charSeq.check new file mode 100644 index 0000000000..f1f374f63e --- /dev/null +++ b/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) == '' diff --git a/test/files/run/array-charSeq.scala b/test/files/run/array-charSeq.scala new file mode 100644 index 0000000000..f7d0586f03 --- /dev/null +++ b/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) + } + } +} |