summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2009-08-28 16:45:27 +0000
committerPaul Phillips <paulp@improving.org>2009-08-28 16:45:27 +0000
commitde60f2481fe773e4435e2a347983dfbf7f7d2d05 (patch)
treecaf1d1d913c41a216a357f0a3d2f94a2be4fdffb
parent36b00f5234b2b3ced155e5bc9da9b239211a9520 (diff)
downloadscala-de60f2481fe773e4435e2a347983dfbf7f7d2d05.tar.gz
scala-de60f2481fe773e4435e2a347983dfbf7f7d2d05.tar.bz2
scala-de60f2481fe773e4435e2a347983dfbf7f7d2d05.zip
Opening, experimental implementation of StringV...
Opening, experimental implementation of StringVector, since I wrote all this yesterday and it'll be useful whether or not we the current compiler-magic proposal for Arrays and Strings pans out.
-rw-r--r--src/library/scala/collection/immutable/StringVector.scala215
1 files changed, 215 insertions, 0 deletions
diff --git a/src/library/scala/collection/immutable/StringVector.scala b/src/library/scala/collection/immutable/StringVector.scala
new file mode 100644
index 0000000000..9dd64abf8a
--- /dev/null
+++ b/src/library/scala/collection/immutable/StringVector.scala
@@ -0,0 +1,215 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.collection.immutable
+
+import util.matching.Regex
+import annotation.experimental
+
+/** An incomplete implementation of all the methods on Vector,
+ * written as static methods which take a String as a faux "this"
+ * argument and which are all entirely String-specific, with the
+ * attendant improvements in performance, return types, etc.
+ * I looked for the fastest way to do these operations so there
+ * is some unattractiveness.
+ *
+ * @author Paul Phillips
+ * @version 2.8
+ */
+
+@experimental
+object StringVector
+{
+ private def noSuch(msg: String) = throw new NoSuchElementException(msg)
+
+ final def foreach[T](s: String, f: Char => T): Unit = {
+ val len = s.length
+ var i = 0
+ while (i < len) {
+ f(s charAt i)
+ i += 1
+ }
+ }
+
+ final def filter(s: String, f: Char => Boolean): String = {
+ val len = s.length
+ val chars = new Array[Char](len)
+ var index, i = 0
+ while (i < len) {
+ val c = s charAt i
+ if (f(c)) {
+ chars(index) = c
+ index += 1
+ }
+ i += 1
+ }
+ if (index == i) s
+ else new String(chars, 0, index)
+ }
+
+ final def map(s: String, f: Char => Char): String = {
+ val len = s.length
+ val chars = new Array[Char](len)
+ var i = 0
+ while (i < len) {
+ chars(i) = f(s charAt i)
+ i += 1
+ }
+ new String(chars, 0, len)
+ }
+
+ final def flatMap(s: String, f: Char => String): String = {
+ val sb = new StringBuilder
+ val len = s.length
+ var i = 0
+ while (i < len) {
+ sb append f(s charAt i)
+ i += 1
+ }
+ sb.toString()
+ }
+
+ final def take(s: String, len: Int): String =
+ if (len <= 0) ""
+ else if (len >= s.length) s
+ else s.substring(0, len)
+
+ final def drop(s: String, len: Int): String =
+ if (len >= s.length) ""
+ else if (len <= 0) s
+ else s.substring(len, s.length)
+
+ final def takeRight(s: String, len: Int): String =
+ if (len <= 0) ""
+ else if (len >= s.length) s
+ else s.substring(s.length - len, s.length)
+
+ final def dropRight(s: String, len: Int): String =
+ if (len <= 0) s
+ else if (len >= s.length) ""
+ else s.substring(0, s.length - len)
+
+ final def splitAt(s: String, index: Int): (String, String) =
+ if (index <= 0) ("", s)
+ else if (index >= s.length) (s, "")
+ else (take(s, index), drop(s, index))
+
+ final def head(s: String): Char =
+ if (s == "") noSuch("head of empty list")
+ else s charAt 0
+
+ final def tail(s: String): String =
+ if (s == "") noSuch("tail of empty list")
+ else drop(s, 1)
+
+ final def last(s: String): Char =
+ if (s == "") noSuch("empty.last")
+ else s charAt (s.length - 1)
+
+ final def init(s: String): String =
+ if (s == "") noSuch("empty.init")
+ else dropRight(s, 1)
+
+ final def endsWith(s: String, suffix: String) =
+ takeRight(s, suffix.length) == suffix
+
+ final def startsWith(s: String, prefix: String, offset: Int = 0) =
+ take(drop(s, offset), prefix.length) == prefix
+
+ final def takeWhile(s: String, f: Char => Boolean) = {
+ val len = s.length
+ var i = 0
+ while (i < len && f(s charAt i)) i += 1
+
+ take(s, i)
+ }
+ final def dropWhile(s: String, f: Char => Boolean) = {
+ val len = s.length
+ var i = 0
+ while (i < len && f(s charAt i)) i += 1
+
+ drop(s, i)
+ }
+ final def indexWhere(s: String, p: Char => Boolean, from: Int = 0): Int = {
+ val len = s.length
+ var i = from
+ while (i < len) {
+ if (p(s charAt i))
+ return i
+ }
+ -1
+ }
+ final def lastIndexWhere(s: String, p: Char => Boolean): Int = lastIndexWhere(s, p, s.length - 1)
+ final def lastIndexWhere(s: String, p: Char => Boolean, end: Int): Int = {
+ var i = end
+ while (i >= 0) {
+ if (p(s charAt i))
+ return i
+ }
+ -1
+ }
+
+ final def reverse(s: String): String = {
+ val sb = new StringBuilder
+ var i = s.length - 1
+ while (i >= 0) {
+ sb append (s charAt i)
+ i -= 1
+ }
+ sb.toString
+ }
+
+ final def find(s: String, p: Char => Boolean): Option[Char] = {
+ val len = s.length
+ var i = 0
+ while (i < len) {
+ val c = s charAt i
+ if (p(c)) return Some(c)
+ }
+ None
+ }
+
+ final def count(s: String, p: Char => Boolean): Int = {
+ val len = s.length
+ var total, i = 0
+ while (i < len)
+ if (p(s charAt i))
+ total += 1
+
+ total
+ }
+ final def headOption(s: String): Option[Char] =
+ if (s.isEmpty) None else Some(s charAt 0)
+ final def lastOption(s: String): Option[Char] =
+ if (s.isEmpty) None else Some(last(s))
+
+ final def slice(s: String, from: Int, to: Int) =
+ s.substring(from, to)
+
+ final def span(s: String, p: Char => Boolean): (String, String) = {
+ val len = s.length
+ var i = 0
+ while (p(s charAt i)) i += 1
+
+ splitAt(s, i)
+ }
+
+ final def partition(s: String, p: Char => Boolean): (String, String) = {
+ val len = s.length
+ val sb1, sb2 = new StringBuilder
+ var i = 0
+ while (i < len) {
+ val c = s charAt i
+ if (p(c)) sb1 append c else sb2 append c
+ i += 1
+ }
+ (sb1.toString, sb2.toString)
+ }
+} \ No newline at end of file