summaryrefslogtreecommitdiff
path: root/src/jvm14-library
diff options
context:
space:
mode:
authorGeoffrey Washburn <geoffrey.washburn@epfl.ch>2008-04-16 10:45:52 +0000
committerGeoffrey Washburn <geoffrey.washburn@epfl.ch>2008-04-16 10:45:52 +0000
commit68caee2e41aff4c689d9850c543be377d3bed12c (patch)
treea4d05dad58c1fe42aa25f44d380318aeda5b442b /src/jvm14-library
parentc89a4108669837744df8e9d2cb4e49df41949718 (diff)
downloadscala-68caee2e41aff4c689d9850c543be377d3bed12c.tar.gz
scala-68caee2e41aff4c689d9850c543be377d3bed12c.tar.bz2
scala-68caee2e41aff4c689d9850c543be377d3bed12c.zip
Add a contains(String) method for 1.4
Diffstat (limited to 'src/jvm14-library')
-rw-r--r--src/jvm14-library/scala/runtime/RichString.scala244
1 files changed, 244 insertions, 0 deletions
diff --git a/src/jvm14-library/scala/runtime/RichString.scala b/src/jvm14-library/scala/runtime/RichString.scala
new file mode 100644
index 0000000000..2496ddc64b
--- /dev/null
+++ b/src/jvm14-library/scala/runtime/RichString.scala
@@ -0,0 +1,244 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala.runtime
+
+import Predef._
+import scala.util.matching.Regex
+
+final class RichString(val self: String) extends Proxy with RandomAccessSeq[Char] with Ordered[String] {
+ import RichString._
+ override def apply(n: Int) = self charAt n
+ override def length = self.length
+ override def toString = self
+ override def mkString = self
+
+ override def slice(from: Int, until: Int): RichString = {
+ val len = self.length
+ new RichString(
+ if (from >= until || from >= len)
+ ""
+ else {
+ val from0 = if (from < 0) 0 else from
+ val until0 = if (until > len) len else until
+ self.substring(from0, until0)
+ }
+ )
+ }
+
+ //override def ++ [B >: A](that: Iterable[B]): Seq[B] = {
+ override def ++[B >: Char](that: Iterable[B]): RandomAccessSeq[B] = that match {
+ case that: RichString => new RichString(self + that.self)
+ case that => super.++(that)
+ }
+
+ override def take(until: Int): RichString = slice(0, until)
+
+ override def drop(from: Int): RichString = slice(from, self.length)
+
+ override def startsWith[B](that: Seq[B]) = that match {
+ case that: RichString => self startsWith that.self
+ case that => super.startsWith(that)
+ }
+
+ override def endsWith[B](that: Seq[B]) = that match {
+ case that: RichString => self endsWith that.self
+ case that => super.endsWith(that)
+ }
+
+ override def indexOf[B](that: Seq[B]) = that match {
+ case that: RichString => self indexOf that.self
+ case that => super.indexOf(that)
+ }
+
+ override def containsSlice[B](that: Seq[B]) = that match {
+ case that: RichString => self contains that.self
+ case that => super.containsSlice(that)
+ }
+
+ def contains(arg: String) : Boolean = {
+ self.matches(""".*\Q"""+arg+"""\E.*""")
+ }
+
+ override def reverse: RichString = {
+ val buf = new StringBuilder
+ var i = self.length - 1
+ while (i >= 0) {
+ buf append (self charAt i)
+ i -= 1
+ }
+ new RichString(buf.toString)
+ }
+
+ /** return n times the current string
+ */
+ def * (n: Int): String = {
+ val buf = new StringBuilder
+ for (i <- 0 until n) buf append self
+ buf.toString
+ }
+
+ override def compare(other: String) = self compareTo other
+
+ private def isLineBreak(c: Char) = c == LF || c == FF
+
+ /** <p>
+ * Strip trailing line end character from this string if it has one.
+ * A line end character is one of
+ * </p>
+ * <ul style="list-style-type: none;">
+ * <li>LF - line feed (0x0A hex)</li>
+ * <li>FF - form feed (0x0C hex)</li>
+ * </ul>
+ * <p>
+ * If a line feed character LF is preceded by a carriage return CR
+ * (0x0D hex), the CR character is also stripped (Windows convention).
+ * </p>
+ */
+ def stripLineEnd: String = {
+ val len = self.length
+ if (len == 0) self
+ else {
+ val last = apply(len - 1)
+ if (isLineBreak(last))
+ self.substring(0, if (last == LF && len >= 2 && apply(len - 2) == CR) len - 2 else len - 1)
+ else
+ self
+ }
+ }
+
+ /** <p>
+ * Return all lines in this string in an iterator, including trailing
+ * line end characters.
+ * </p>
+ * <p>
+ * The number of strings returned is one greater than the number of line
+ * end characters in this string. For an empty string, a single empty
+ * line is returned. A line end character is one of
+ * </p>
+ * <ul style="list-style-type: none;">
+ * <li>LF - line feed (0x0A hex)</li>
+ * <li>FF - form feed (0x0C hex)</li>
+ * </ul>
+ */
+ def linesWithSeparators = new Iterator[String] {
+ val len = self.length
+ var index = 0
+ def hasNext: Boolean = index < len
+ def next(): String = {
+ if (index >= len) throw new NoSuchElementException("next on empty iterator")
+ val start = index
+ while (index < len && !isLineBreak(apply(index))) index += 1
+ index += 1
+ self.substring(start, index min len)
+ }
+ }
+
+ /** Return all lines in this string in an iterator, excluding trailing line
+ * end characters, i.e. apply <code>.stripLineEnd</code> to all lines
+ * returned by <code>linesWithSeparators</code>.
+ */
+ def lines: Iterator[String] =
+ linesWithSeparators map (line => new RichString(line).stripLineEnd)
+
+ /** Returns this string with first character converted to upper case */
+ def capitalize: String =
+ if (self == null) null
+ else if (self.length == 0) ""
+ else {
+ val chars = self.toCharArray
+ chars(0) = chars(0).toUpperCase
+ new String(chars)
+ }
+
+ /** <p>
+ * For every line in this string:
+ * </p>
+ * <blockquote>
+ * Strip a leading prefix consisting of blanks or control characters
+ * followed by <code>marginChar</code> from the line.
+ * </blockquote>
+ */
+ def stripMargin(marginChar: Char): String = {
+ val buf = new StringBuilder
+ for (line <- linesWithSeparators) {
+ val len = line.length
+ var index = 0
+ while (index < len && line.charAt(index) <= ' ') index += 1
+ buf append
+ (if (index < len && line.charAt(index) == marginChar) line.substring(index + 1) else line)
+ }
+ buf.toString
+ }
+
+ /** <p>
+ * For every line in this string:
+ * </p>
+ * <blockquote>
+ * Strip a leading prefix consisting of blanks or control characters
+ * followed by <code>|</code> from the line.
+ * </blockquote>
+ */
+ def stripMargin: String = stripMargin('|')
+
+ // NB. "\\Q" + '\\' + "\\E" works on Java 1.5 and newer, but not on Java 1.4
+ private def escape(ch: Char): String = ch match {
+ case '\\' => "\\\\"
+ case _ => "\\Q"+ch+"\\E"
+ }
+
+ @throws(classOf[java.util.regex.PatternSyntaxException])
+ def split(separator: Char): Array[String] = self.split(escape(separator))
+
+ @throws(classOf[java.util.regex.PatternSyntaxException])
+ def split(separators: Array[Char]): Array[String] = {
+ val re = separators.foldLeft("[")(_+escape(_)) + "]"
+ self.split(re)
+ }
+
+ /** You can follow a string with `.r', turning
+ * it into a Regex. E.g.
+ *
+ * """A\w*""".r is the regular expression for identifiers starting with `A'.
+ */
+ def r: Regex = new Regex(self)
+
+ def toBoolean: Boolean = parseBoolean(self)
+ def toByte: Byte = java.lang.Byte.parseByte(self)
+ def toShort: Short = java.lang.Short.parseShort(self)
+ def toInt: Int = java.lang.Integer.parseInt(self)
+ def toLong: Long = java.lang.Long.parseLong(self)
+ def toFloat: Float = java.lang.Float.parseFloat(self)
+ def toDouble: Double = java.lang.Double.parseDouble(self)
+
+ def toArray: Array[Char] = {
+ val result = new Array[Char](length)
+ self.getChars(0, length, result, 0)
+ result
+ }
+}
+
+object RichString {
+ // just statics for rich string.
+ private final val LF: Char = 0x0A
+ private final val FF: Char = 0x0C
+ private final val CR: Char = 0x0D
+ private final val SU: Char = 0x1A
+
+ private def parseBoolean(s: String): Boolean =
+ if (s != null) s.toLowerCase match {
+ case "true" => true
+ case "false" => false
+ case _ => throw new NumberFormatException("For input string: \""+s+"\"")
+ }
+ else
+ throw new NumberFormatException("For input string: \"null\"")
+}