From 68caee2e41aff4c689d9850c543be377d3bed12c Mon Sep 17 00:00:00 2001 From: Geoffrey Washburn Date: Wed, 16 Apr 2008 10:45:52 +0000 Subject: Add a contains(String) method for 1.4 --- src/jvm14-library/scala/runtime/RichString.scala | 244 +++++++++++++++++++++++ 1 file changed, 244 insertions(+) create mode 100644 src/jvm14-library/scala/runtime/RichString.scala (limited to 'src/jvm14-library') 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 + + /**

+ * Strip trailing line end character from this string if it has one. + * A line end character is one of + *

+ * + *

+ * If a line feed character LF is preceded by a carriage return CR + * (0x0D hex), the CR character is also stripped (Windows convention). + *

+ */ + 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 + } + } + + /**

+ * Return all lines in this string in an iterator, including trailing + * line end characters. + *

+ *

+ * 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 + *

+ * + */ + 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 .stripLineEnd to all lines + * returned by linesWithSeparators. + */ + 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) + } + + /**

+ * For every line in this string: + *

+ *
+ * Strip a leading prefix consisting of blanks or control characters + * followed by marginChar from the line. + *
+ */ + 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 + } + + /**

+ * For every line in this string: + *

+ *
+ * Strip a leading prefix consisting of blanks or control characters + * followed by | from the line. + *
+ */ + 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\"") +} -- cgit v1.2.3