You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2016/05/31 02:01:01 UTC
[1/3] groovy git commit: GROOVY-6950: StringGroovyMethods minor
performance improvements (avoid calling toString)
Repository: groovy
Updated Branches:
refs/heads/master a88c03474 -> 432a8e5ed
GROOVY-6950: StringGroovyMethods minor performance improvements (avoid calling toString)
Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/24043a5c
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/24043a5c
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/24043a5c
Branch: refs/heads/master
Commit: 24043a5c56fc020d8a5e633f7bd862033cbecf75
Parents: a88c034
Author: paulk <pa...@asert.com.au>
Authored: Mon May 30 17:46:28 2016 +1000
Committer: paulk <pa...@asert.com.au>
Committed: Mon May 30 17:46:28 2016 +1000
----------------------------------------------------------------------
.../groovy/runtime/StringGroovyMethods.java | 115 ++++++++-----------
.../groovy/GroovyCharSequenceMethodsTest.groovy | 95 ++++++++-------
2 files changed, 95 insertions(+), 115 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/groovy/blob/24043a5c/src/main/org/codehaus/groovy/runtime/StringGroovyMethods.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/runtime/StringGroovyMethods.java b/src/main/org/codehaus/groovy/runtime/StringGroovyMethods.java
index d782810..058b270 100644
--- a/src/main/org/codehaus/groovy/runtime/StringGroovyMethods.java
+++ b/src/main/org/codehaus/groovy/runtime/StringGroovyMethods.java
@@ -257,9 +257,8 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
* @since 2.5.0
*/
public static String uncapitalize(CharSequence self) {
- String s = self.toString();
- if (s == null || s.length() == 0) return s;
- return Character.toLowerCase(s.charAt(0)) + s.substring(1);
+ if (self.length() == 0) return "";
+ return "" + Character.toLowerCase(self.charAt(0)) + self.subSequence(1, self.length());
}
/**
@@ -279,9 +278,8 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
* @since 1.8.2
*/
public static String capitalize(CharSequence self) {
- String s = self.toString();
- if (s == null || s.length() == 0) return s;
- return Character.toUpperCase(s.charAt(0)) + s.substring(1);
+ if (self.length() == 0) return "";
+ return "" + Character.toUpperCase(self.charAt(0)) + self.subSequence(1, self.length());
}
/**
@@ -341,20 +339,19 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
* @since 1.8.2
*/
public static String center(CharSequence self, Number numberOfChars, CharSequence padding) {
- String s = self.toString();
String padding1 = padding.toString();
int numChars = numberOfChars.intValue();
- if (numChars <= s.length()) {
- return s;
+ if (numChars <= self.length()) {
+ return self.toString();
} else {
- int charsToAdd = numChars - s.length();
+ int charsToAdd = numChars - self.length();
String semiPad = charsToAdd % 2 == 1 ?
getPadding(padding1, charsToAdd / 2 + 1) :
getPadding(padding1, charsToAdd / 2);
if (charsToAdd % 2 == 0)
- return semiPad + s + semiPad;
+ return semiPad + self + semiPad;
else
- return semiPad.substring(0, charsToAdd / 2) + s + semiPad;
+ return semiPad.substring(0, charsToAdd / 2) + self + semiPad;
}
}
@@ -440,7 +437,6 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
* @since 1.8.2
*/
public static String denormalize(final CharSequence self) {
- final String s = self.toString();
// Don't do this in static initializer because we may never be needed.
// TODO: Put this lineSeparator property somewhere everyone can use it.
if (lineSeparator == null) {
@@ -459,10 +455,10 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
}
}
- final int len = s.length();
+ final int len = self.length();
if (len < 1) {
- return s;
+ return self.toString();
}
final StringBuilder sb = new StringBuilder((110 * len) / 100);
@@ -470,14 +466,14 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
int i = 0;
while (i < len) {
- final char ch = s.charAt(i++);
+ final char ch = self.charAt(i++);
switch (ch) {
case '\r':
sb.append(lineSeparator);
// Eat the following LF if any.
- if ((i < len) && (s.charAt(i) == '\n')) {
+ if ((i < len) && (self.charAt(i) == '\n')) {
++i;
}
@@ -826,23 +822,22 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
* @since 1.8.2
*/
public static String expand(CharSequence self, int tabStop) {
- String s = self.toString();
- if (s.length() == 0) return s;
+ if (self.length() == 0) return self.toString();
try {
StringBuilder builder = new StringBuilder();
- for (String line : readLines(s)) {
- builder.append(expandLine(line, tabStop));
+ for (String line : readLines(self)) {
+ builder.append(expandLine((CharSequence)line, tabStop));
builder.append("\n");
}
// remove the normalized ending line ending if it was not present
- if (!s.endsWith("\n")) {
+ if (self.charAt(self.length() - 1) != '\n') {
builder.deleteCharAt(builder.length() - 1);
}
return builder.toString();
} catch (IOException e) {
/* ignore */
}
- return s;
+ return self.toString();
}
/**
@@ -1573,11 +1568,11 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
return counter;
}
- private static String getPadding(String padding, int length) {
+ private static String getPadding(CharSequence padding, int length) {
if (padding.length() < length) {
return multiply(padding, length / padding.length() + 1).substring(0, length);
} else {
- return padding.substring(0, length);
+ return "" + padding.subSequence(0, length);
}
}
@@ -1632,9 +1627,8 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
* @since 1.8.2
*/
public static boolean isAllWhitespace(CharSequence self) {
- String s = self.toString();
- for (int i = 0; i < s.length(); i++) {
- if (!Character.isWhitespace(s.charAt(i)))
+ for (int i = 0; i < self.length(); i++) {
+ if (!Character.isWhitespace(self.charAt(i)))
return false;
}
return true;
@@ -1720,11 +1714,10 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
* @since 1.8.2
*/
public static boolean isCase(CharSequence caseValue, Object switchValue) {
- String s = caseValue.toString();
if (switchValue == null) {
- return s == null;
+ return caseValue == null;
}
- return s.equals(switchValue.toString());
+ return caseValue.toString().equals(switchValue.toString());
}
/**
@@ -2096,16 +2089,15 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
* @since 1.8.2
*/
public static String multiply(CharSequence self, Number factor) {
- String s = self.toString();
int size = factor.intValue();
if (size == 0)
return "";
else if (size < 0) {
throw new IllegalArgumentException("multiply() should be called with a number of 0 or greater not: " + size);
}
- StringBuilder answer = new StringBuilder(s);
+ StringBuilder answer = new StringBuilder(self);
for (int i = 1; i < size; i++) {
- answer.append(s);
+ answer.append(self);
}
return answer.toString();
}
@@ -2265,12 +2257,11 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
* @since 1.8.2
*/
public static String padLeft(CharSequence self, Number numberOfChars, CharSequence padding) {
- String s = self.toString();
int numChars = numberOfChars.intValue();
- if (numChars <= s.length()) {
- return s;
+ if (numChars <= self.length()) {
+ return self.toString();
} else {
- return getPadding(padding.toString(), numChars - s.length()) + s;
+ return getPadding(padding.toString(), numChars - self.length()) + self;
}
}
@@ -2343,12 +2334,11 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
* @since 1.8.2
*/
public static String padRight(CharSequence self, Number numberOfChars, CharSequence padding) {
- String s = self.toString();
int numChars = numberOfChars.intValue();
- if (numChars <= s.length()) {
- return s;
+ if (numChars <= self.length()) {
+ return self.toString();
} else {
- return s + getPadding(padding.toString(), numChars - s.length());
+ return self + getPadding(padding.toString(), numChars - self.length());
}
}
@@ -3134,11 +3124,10 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
* @since 1.8.2
*/
public static String stripIndent(CharSequence self) {
- String s = self.toString();
- if (s.length() == 0) return s;
+ if (self.length() == 0) return self.toString();
int runningCount = -1;
try {
- for (String line : readLines((CharSequence) s)) {
+ for (String line : readLines(self)) {
// don't take blank lines into account for calculating the indent
if (isAllWhitespace((CharSequence) line)) continue;
if (runningCount == -1) runningCount = line.length();
@@ -3148,7 +3137,7 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
} catch (IOException e) {
/* ignore */
}
- return stripIndent(s, runningCount == -1 ? 0 : runningCount);
+ return stripIndent(self, runningCount == -1 ? 0 : runningCount);
}
/**
@@ -3164,11 +3153,10 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
* @since 1.8.2
*/
public static String stripIndent(CharSequence self, int numChars) {
- String s = self.toString();
- if (s.length() == 0 || numChars <= 0) return s;
+ if (self.length() == 0 || numChars <= 0) return self.toString();
try {
StringBuilder builder = new StringBuilder();
- for (String line : readLines((CharSequence) s)) {
+ for (String line : readLines(self)) {
// normalize an empty or whitespace line to \n
// or strip the indent for lines containing non-space characters
if (!isAllWhitespace((CharSequence) line)) {
@@ -3177,14 +3165,14 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
builder.append("\n");
}
// remove the normalized ending line ending if it was not present
- if (!s.endsWith("\n")) {
+ if (self.charAt(self.length() - 1) != '\n') {
builder.deleteCharAt(builder.length() - 1);
}
return builder.toString();
} catch (IOException e) {
/* ignore */
}
- return s;
+ return self.toString();
}
/**
@@ -3245,23 +3233,22 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
* @since 1.8.2
*/
public static String stripMargin(CharSequence self, char marginChar) {
- String s = self.toString();
- if (s.length() == 0) return s;
+ if (self.length() == 0) return self.toString();
try {
StringBuilder builder = new StringBuilder();
- for (String line : readLines((CharSequence) s)) {
+ for (String line : readLines(self)) {
builder.append(stripMarginFromLine(line, marginChar));
builder.append("\n");
}
// remove the normalized ending line ending if it was not present
- if (!s.endsWith("\n")) {
+ if (self.charAt(self.length() - 1) != '\n') {
builder.deleteCharAt(builder.length() - 1);
}
return builder.toString();
} catch (IOException e) {
/* ignore */
}
- return s;
+ return self.toString();
}
/**
@@ -3275,11 +3262,10 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
* @since 1.8.2
*/
public static String stripMargin(CharSequence self, CharSequence marginChar) {
- String s = self.toString();
String mc = marginChar.toString();
- if (mc == null || mc.length() == 0) return stripMargin((CharSequence) s, '|');
+ if (mc.length() == 0) return stripMargin(self, '|');
// TODO IllegalArgumentException for marginChar.length() > 1 ? Or support String as marker?
- return stripMargin((CharSequence) s, mc.charAt(0));
+ return stripMargin(self, mc.charAt(0));
}
/**
@@ -3763,23 +3749,22 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
* @since 1.8.2
*/
public static String unexpand(CharSequence self, int tabStop) {
- String s = self.toString();
- if (s.length() == 0) return s;
+ if (self.length() == 0) return self.toString();
try {
StringBuilder builder = new StringBuilder();
- for (String line : readLines((CharSequence) s)) {
- builder.append(unexpandLine(line, tabStop));
+ for (String line : readLines(self)) {
+ builder.append(unexpandLine((CharSequence)line, tabStop));
builder.append("\n");
}
// remove the normalized ending line ending if it was not present
- if (!s.endsWith("\n")) {
+ if (self.charAt(self.length() - 1) != '\n') {
builder.deleteCharAt(builder.length() - 1);
}
return builder.toString();
} catch (IOException e) {
/* ignore */
}
- return s;
+ return self.toString();
}
/**
http://git-wip-us.apache.org/repos/asf/groovy/blob/24043a5c/src/test/groovy/GroovyCharSequenceMethodsTest.groovy
----------------------------------------------------------------------
diff --git a/src/test/groovy/GroovyCharSequenceMethodsTest.groovy b/src/test/groovy/GroovyCharSequenceMethodsTest.groovy
index 0e40f2c..3554e8d 100644
--- a/src/test/groovy/GroovyCharSequenceMethodsTest.groovy
+++ b/src/test/groovy/GroovyCharSequenceMethodsTest.groovy
@@ -20,33 +20,28 @@ package groovy
/**
* Tests for DGM methods on CharSequence.
- *
- * @author Paul King
*/
class GroovyCharSequenceMethodsTest extends GroovyTestCase {
- def s1 = 'Today is Thu Jul 28 06:38:07 EST 2011'
- def cs1 = [
- toString:{ -> s1 },
- subSequence:{ int f, int t -> s1.substring(f, t) },
- length:{ -> s1.length() },
- charAt:{ int i -> s1.chars[i] },
- ] as CharSequence
- def s2 = 'Foobar'
- def cs2 = [
- toString:{ -> s2 },
- subSequence:{ int f, int t -> s2.substring(f, t) },
- length:{ -> s2.length() },
- charAt:{ int i -> s2.chars[i] },
- ] as CharSequence
- def cs3 = [
- toString: { -> '''\
+ private static CharSequence makeCharSequence(String s) {
+ [
+ toString : { -> s },
+ subSequence: { int f, int t -> s.substring(f, t) },
+ length : { -> s.length() },
+ charAt : { int i -> s.chars[i] },
+ ] as CharSequence
+ }
+
+ def cs1 = makeCharSequence('Today is Thu Jul 28 06:38:07 EST 2011')
+
+ def cs2 = makeCharSequence('Foobar')
+
+ def cs3 = makeCharSequence('''\
|Foo
|bar
- |'''
- }
- ] as CharSequence
- def csEmpty = [toString:{->''}, length:{->0}] as CharSequence
+ |''')
+
+ def csEmpty = makeCharSequence('')
void testIsCase() {
// direct
@@ -95,7 +90,7 @@ class GroovyCharSequenceMethodsTest extends GroovyTestCase {
void testIsAllWhitespace() {
assert !cs2.isAllWhitespace()
- assert ([toString:{->' \t\n\r'}] as CharSequence).isAllWhitespace()
+ assert makeCharSequence(' \t\n\r').isAllWhitespace()
}
void testReplace() {
@@ -109,7 +104,7 @@ class GroovyCharSequenceMethodsTest extends GroovyTestCase {
}
void testFind() {
- def csDigits = [toString:{->/\d{4}/}] as CharSequence
+ def csDigits = makeCharSequence(/\d{4}/)
assert cs1.find(csDigits) == '2011'
assert cs1.find(csDigits, {"--$it--"}) == '--2011--'
assert cs1.find(~/\d\d:\d\d/) == '06:38'
@@ -117,7 +112,7 @@ class GroovyCharSequenceMethodsTest extends GroovyTestCase {
}
void testFindAll() {
- def csDigits = [toString:{->/\d\d/}] as CharSequence
+ def csDigits = makeCharSequence(/\d\d/)
assert cs1.findAll(csDigits) == ['28', '06', '38', '07', '20', '11']
assert cs1.findAll(csDigits, {"<$it>"}) == ['<28>', '<06>', '<38>', '<07>', '<20>', '<11>']
assert cs1.findAll(~/\s\d\d/) == [' 28', ' 06', ' 20']
@@ -165,30 +160,30 @@ class GroovyCharSequenceMethodsTest extends GroovyTestCase {
}
void testCapitalize() {
- def csfoo = [toString:{->'foo'}] as CharSequence
+ def csfoo = makeCharSequence('foo')
assert csfoo.capitalize() == 'Foo'
assert cs2.capitalize() == 'Foobar'
}
void testUncapitalize() {
- def csfoo = [toString:{->'Foo'}] as CharSequence
+ def csfoo = makeCharSequence('Foo')
assert csfoo.uncapitalize() == 'foo'
assert cs2.uncapitalize() == 'foobar'
}
void testExpand() {
- def csfoobar = [toString:{->'foo\tbar'}] as CharSequence
+ def csfoobar = makeCharSequence('foo\tbar')
assert csfoobar.expand() == 'foo bar'
assert csfoobar.expand(4) == 'foo bar'
- csfoobar = [toString:{->'\tfoo\n\tbar'}] as CharSequence
+ csfoobar = makeCharSequence('\tfoo\n\tbar')
assert csfoobar.expand(4) == ' foo\n bar'
}
void testUnexpand() {
- def csfoobar = [toString:{->'foo bar'}] as CharSequence
+ def csfoobar = makeCharSequence('foo bar')
assert csfoobar.unexpand() == 'foo\tbar'
assert csfoobar.unexpand(4) == 'foo\t\tbar'
- csfoobar = [toString:{->' foo\n bar'}] as CharSequence
+ csfoobar = makeCharSequence(' foo\n bar')
assert csfoobar.unexpand(4) == '\t foo\n\tbar'
}
@@ -198,22 +193,22 @@ class GroovyCharSequenceMethodsTest extends GroovyTestCase {
}
void testMinus() {
- def csoo = [toString:{->'oo'}] as CharSequence
+ def csoo = makeCharSequence('oo')
assert cs2.minus(42) == 'Foobar'
assert cs2.minus(csoo) == 'Fbar'
assert cs2 - csoo == 'Fbar'
}
void testContains() {
- def csoo = [toString:{->'oo'}] as CharSequence
- def csbaz = [toString:{->'baz'}] as CharSequence
+ def csoo = makeCharSequence('oo')
+ def csbaz = makeCharSequence('baz')
assert cs2.contains(csoo)
assert !cs2.contains(csbaz)
}
void testCount() {
- def cszero = [toString:{->'0'}] as CharSequence
- def csbar = [toString:{->'|'}] as CharSequence
+ def cszero = makeCharSequence('0')
+ def csbar = makeCharSequence('|')
assert cs1.count(cszero) == 3
assert cs3.count(csbar) == 3
}
@@ -234,7 +229,7 @@ class GroovyCharSequenceMethodsTest extends GroovyTestCase {
}
void testToInteger() {
- def csFourteen = [toString:{->'014'}] as CharSequence
+ def csFourteen = makeCharSequence('014')
assert csFourteen.isInteger()
def fourteen = csFourteen.toInteger()
assert fourteen instanceof Integer
@@ -242,7 +237,7 @@ class GroovyCharSequenceMethodsTest extends GroovyTestCase {
}
void testToLong() {
- def csFourteen = [toString:{->'014'}] as CharSequence
+ def csFourteen = makeCharSequence('014')
assert csFourteen.isLong()
def fourteen = csFourteen.toLong()
assert fourteen instanceof Long
@@ -250,14 +245,14 @@ class GroovyCharSequenceMethodsTest extends GroovyTestCase {
}
void testToShort() {
- def csFourteen = [toString:{->'014'}] as CharSequence
+ def csFourteen = makeCharSequence('014')
def fourteen = csFourteen.toShort()
assert fourteen instanceof Short
assert fourteen == 14
}
void testToBigInteger() {
- def csFourteen = [toString:{->'014'}] as CharSequence
+ def csFourteen = makeCharSequence('014')
assert csFourteen.isBigInteger()
def fourteen = csFourteen.toBigInteger()
assert fourteen instanceof BigInteger
@@ -265,7 +260,7 @@ class GroovyCharSequenceMethodsTest extends GroovyTestCase {
}
void testToFloat() {
- def csThreePointFive = [toString:{->'3.5'}] as CharSequence
+ def csThreePointFive = makeCharSequence('3.5')
assert csThreePointFive.isFloat()
def threePointFive = csThreePointFive.toFloat()
assert threePointFive instanceof Float
@@ -273,7 +268,7 @@ class GroovyCharSequenceMethodsTest extends GroovyTestCase {
}
void testToDouble() {
- def csThreePointFive = [toString:{->'3.5'}] as CharSequence
+ def csThreePointFive = makeCharSequence('3.5')
assert csThreePointFive.isDouble()
def threePointFive = csThreePointFive.toDouble()
assert threePointFive instanceof Double
@@ -281,7 +276,7 @@ class GroovyCharSequenceMethodsTest extends GroovyTestCase {
}
void testToBigDecimal() {
- def csThreePointFive = [toString:{->'3.5'}] as CharSequence
+ def csThreePointFive = makeCharSequence('3.5')
assert csThreePointFive.isBigDecimal()
assert csThreePointFive.isNumber()
def threePointFive = csThreePointFive.toBigDecimal()
@@ -300,8 +295,8 @@ class GroovyCharSequenceMethodsTest extends GroovyTestCase {
void testSplitEachLine() {
def regexOp = /\s*\*\s*/
- def csOp = [toString:{->regexOp}] as CharSequence
- def csTwoLines = [toString:{->'10*15\n11 * 9'}] as CharSequence
+ def csOp = makeCharSequence(regexOp)
+ def csTwoLines = makeCharSequence('10*15\n11 * 9')
def result = []
csTwoLines.splitEachLine(csOp){ left, right -> result << left.toInteger() * right.toInteger() }
assert result == [150, 99]
@@ -342,7 +337,7 @@ class GroovyCharSequenceMethodsTest extends GroovyTestCase {
private enum Coin { penny, nickel, dime, quarter }
void testAsType() {
- def csDime = [toString:{->'dime'}] as CharSequence
+ def csDime = makeCharSequence('dime')
def dime = csDime as Coin
assert dime instanceof Coin
assert dime == Coin.dime
@@ -351,7 +346,7 @@ class GroovyCharSequenceMethodsTest extends GroovyTestCase {
void testEachMatch() {
def result = []
def regexDigits = /(\d)(.)(\d)/
- def csDigits = [toString:{->regexDigits}] as CharSequence
+ def csDigits = makeCharSequence(regexDigits)
assert cs1.eachMatch(csDigits) { all, first, delim, second -> result << "$first $delim $second" }
assert result == ['8 0', '6 : 3', '8 : 0', '2 0 1']
result = []
@@ -364,8 +359,8 @@ class GroovyCharSequenceMethodsTest extends GroovyTestCase {
}
void testReplaceAllFirst() {
- def csDigit = [toString:{->/\d/}] as CharSequence
- def csUnder = [toString:{->/_/}] as CharSequence
+ def csDigit = makeCharSequence(/\d/)
+ def csUnder = makeCharSequence(/_/)
assert cs1.replaceAll(~/\d/, csUnder) == 'Today is Thu Jul __ __:__:__ EST ____'
assert cs1.replaceAll(csDigit, csUnder) == 'Today is Thu Jul __ __:__:__ EST ____'
@@ -377,7 +372,7 @@ class GroovyCharSequenceMethodsTest extends GroovyTestCase {
void testNormalizeDenormalize() {
def text = 'the quick brown\nfox jumped\r\nover the lazy dog'
- def csText = [toString : { -> text }] as CharSequence
+ def csText = makeCharSequence(text)
assert csText.normalize() == text.normalize()
assert csText.normalize().denormalize() == text.normalize().denormalize()
}
[3/3] groovy git commit: GROOVY-6950: StringGroovyMethods minor
performance improvements (minor refactoring - closes #341)
Posted by pa...@apache.org.
GROOVY-6950: StringGroovyMethods minor performance improvements (minor refactoring - closes #341)
Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/432a8e5e
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/432a8e5e
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/432a8e5e
Branch: refs/heads/master
Commit: 432a8e5ed18960812887273187fd07debed20614
Parents: 35b5f34
Author: paulk <pa...@asert.com.au>
Authored: Tue May 31 11:53:17 2016 +1000
Committer: paulk <pa...@asert.com.au>
Committed: Tue May 31 11:58:07 2016 +1000
----------------------------------------------------------------------
.../groovy/runtime/StringGroovyMethods.java | 66 +++++++++-----------
.../groovy/util/CharSequenceReader.java | 12 ++--
2 files changed, 34 insertions(+), 44 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/groovy/blob/432a8e5e/src/main/org/codehaus/groovy/runtime/StringGroovyMethods.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/runtime/StringGroovyMethods.java b/src/main/org/codehaus/groovy/runtime/StringGroovyMethods.java
index 665f606..2c8f794 100644
--- a/src/main/org/codehaus/groovy/runtime/StringGroovyMethods.java
+++ b/src/main/org/codehaus/groovy/runtime/StringGroovyMethods.java
@@ -34,14 +34,12 @@ import org.codehaus.groovy.util.CharSequenceReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
-import java.io.StringReader;
import java.io.StringWriter;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -49,7 +47,6 @@ import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.StringTokenizer;
-import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -166,25 +163,25 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
@SuppressWarnings("unchecked")
public static <T> T asType(String self, Class<T> c) {
if (c == List.class) {
- return (T) toList(self);
+ return (T) toList((CharSequence)self);
} else if (c == BigDecimal.class) {
- return (T) toBigDecimal(self);
+ return (T) toBigDecimal((CharSequence)self);
} else if (c == BigInteger.class) {
- return (T) toBigInteger(self);
+ return (T) toBigInteger((CharSequence)self);
} else if (c == Long.class || c == Long.TYPE) {
- return (T) toLong(self);
+ return (T) toLong((CharSequence)self);
} else if (c == Integer.class || c == Integer.TYPE) {
- return (T) toInteger(self);
+ return (T) toInteger((CharSequence)self);
} else if (c == Short.class || c == Short.TYPE) {
- return (T) toShort(self);
+ return (T) toShort((CharSequence)self);
} else if (c == Byte.class || c == Byte.TYPE) {
return (T) Byte.valueOf(self.trim());
} else if (c == Character.class || c == Character.TYPE) {
return (T) toCharacter(self);
} else if (c == Double.class || c == Double.TYPE) {
- return (T) toDouble(self);
+ return (T) toDouble((CharSequence)self);
} else if (c == Float.class || c == Float.TYPE) {
- return (T) toFloat(self);
+ return (T) toFloat((CharSequence)self);
} else if (c == File.class) {
return (T) new File(self);
} else if (c.isEnum()) {
@@ -910,7 +907,7 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
* @since 1.8.2
*/
public static String find(CharSequence self, CharSequence regex, @ClosureParams(value=SimpleType.class, options="java.lang.String[]") Closure closure) {
- return find(self.toString(), Pattern.compile(regex.toString()), closure);
+ return find(self, Pattern.compile(regex.toString()), closure);
}
/**
@@ -1506,7 +1503,7 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
RangeInfo info = subListBorders(text.length(), range);
String answer = text.substring(info.from, info.to);
if (info.reverse) {
- answer = reverse(answer);
+ answer = reverse((CharSequence)answer);
}
return answer;
}
@@ -2463,11 +2460,10 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
*
* @param self a CharSequence object
* @return a list of lines
- * @throws java.io.IOException if an error occurs
* @since 1.8.2
*/
- public static List<String> readLines(CharSequence self) throws IOException {
- return IOGroovyMethods.readLines(new StringReader(self.toString()));
+ public static List<String> readLines(CharSequence self) {
+ return DefaultGroovyMethods.toList(new LineIterable(self));
}
/**
@@ -2475,7 +2471,7 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
* @see #readLines(CharSequence)
*/
@Deprecated
- public static List<String> readLines(String self) throws IOException {
+ public static List<String> readLines(String self) {
return readLines((CharSequence) self);
}
@@ -2496,9 +2492,9 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
}
/**
- * Replaces all occurrences of a captured group by the result of a closure on that text.
+ * Replaces all occurrences of a captured group by the result of calling a closure on that text.
* <p>
- * For examples,
+ * Examples:
* <pre class="groovyTestCase">
* assert "hello world".replaceAll("(o)") { it[0].toUpperCase() } == "hellO wOrld"
*
@@ -2771,7 +2767,8 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
private static class ReplaceState {
public ReplaceState(Map<CharSequence, CharSequence> replacements) {
this.noMoreMatches = new boolean[replacements.size()];
- this.replacementsList = DefaultGroovyMethods.toList(replacements.entrySet());
+ this.replacementsList = DefaultGroovyMethods.toList((Iterable<Map.Entry<CharSequence,CharSequence>>)
+ replacements.entrySet());
}
int textIndex = -1;
@@ -3058,13 +3055,11 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
* @param pattern the regular expression Pattern for the delimiter
* @param closure a closure
* @return the last value returned by the closure
- * @throws java.io.IOException if an error occurs
* @since 1.8.2
*/
- public static <T> T splitEachLine(CharSequence self, Pattern pattern, @ClosureParams(value=FromString.class,options={"List<String>","String[]"},conflictResolutionStrategy=PickFirstResolver.class) Closure<T> closure) throws IOException {
- final List<String> list = readLines(self);
+ public static <T> T splitEachLine(CharSequence self, Pattern pattern, @ClosureParams(value=FromString.class,options={"List<String>","String[]"},conflictResolutionStrategy=PickFirstResolver.class) Closure<T> closure) {
T result = null;
- for (String line : list) {
+ for (String line : new LineIterable(self)) {
List vals = Arrays.asList(pattern.split(line));
result = closure.call(vals);
}
@@ -3716,21 +3711,16 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
*/
public static String unexpand(CharSequence self, int tabStop) {
if (self.length() == 0) return self.toString();
- try {
- StringBuilder builder = new StringBuilder();
- for (String line : readLines(self)) {
- builder.append(unexpandLine((CharSequence)line, tabStop));
- builder.append("\n");
- }
- // remove the normalized ending line ending if it was not present
- if (self.charAt(self.length() - 1) != '\n') {
- builder.deleteCharAt(builder.length() - 1);
- }
- return builder.toString();
- } catch (IOException e) {
- /* ignore */
+ StringBuilder builder = new StringBuilder();
+ for (String line : new LineIterable(self)) {
+ builder.append(unexpandLine((CharSequence)line, tabStop));
+ builder.append("\n");
}
- return self.toString();
+ // remove the normalized ending line ending if it was not present
+ if (self.charAt(self.length() - 1) != '\n') {
+ builder.deleteCharAt(builder.length() - 1);
+ }
+ return builder.toString();
}
/**
http://git-wip-us.apache.org/repos/asf/groovy/blob/432a8e5e/src/main/org/codehaus/groovy/util/CharSequenceReader.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/util/CharSequenceReader.java b/src/main/org/codehaus/groovy/util/CharSequenceReader.java
index 2154002..cc5f210 100644
--- a/src/main/org/codehaus/groovy/util/CharSequenceReader.java
+++ b/src/main/org/codehaus/groovy/util/CharSequenceReader.java
@@ -27,14 +27,14 @@ import java.io.Serializable;
* StringBuilder, CharBuffer or GString.
* <p>
* <strong>Note:</strong> Supports {@link #mark(int)} and {@link #reset()}.
+ * <p>
+ * <strong>Note:</strong> This class is mostly a copy from Commons IO and
+ * is intended for internal Groovy usage only. It may be deprecated and
+ * removed from Groovy at a faster pace than other classes. If you need this
+ * functionality in your Groovy programs, we recommend using the Commons IO
+ * equivalent directly.
*/
public class CharSequenceReader extends Reader implements Serializable {
- /*
- NOTE: nearly 100% borrowed from Commons-IO but we don't want to bring
- in that whole package just yet. We need to consider reworking all of our
- IO in light of Java 8 streams and decide whether it makes sense to bring
- in an external package.
- */
private static final long serialVersionUID = -6661279371843310693L;
private final CharSequence charSequence;
private int idx;
[2/3] groovy git commit: GROOVY-6950: StringGroovyMethods minor
performance improvements (make use of line based iterator)
Posted by pa...@apache.org.
GROOVY-6950: StringGroovyMethods minor performance improvements (make use of line based iterator)
Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/35b5f345
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/35b5f345
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/35b5f345
Branch: refs/heads/master
Commit: 35b5f3450788601e5bad8a18b5a4758663fedebb
Parents: 24043a5
Author: paulk <pa...@asert.com.au>
Authored: Mon May 30 21:11:46 2016 +1000
Committer: paulk <pa...@asert.com.au>
Committed: Mon May 30 21:11:46 2016 +1000
----------------------------------------------------------------------
.../groovy/runtime/StringGroovyMethods.java | 146 ++++++----------
.../groovy/util/CharSequenceReader.java | 170 +++++++++++++++++++
2 files changed, 226 insertions(+), 90 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/groovy/blob/35b5f345/src/main/org/codehaus/groovy/runtime/StringGroovyMethods.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/runtime/StringGroovyMethods.java b/src/main/org/codehaus/groovy/runtime/StringGroovyMethods.java
index 058b270..665f606 100644
--- a/src/main/org/codehaus/groovy/runtime/StringGroovyMethods.java
+++ b/src/main/org/codehaus/groovy/runtime/StringGroovyMethods.java
@@ -29,6 +29,7 @@ import groovy.transform.stc.FromString;
import groovy.transform.stc.PickFirstResolver;
import groovy.transform.stc.SimpleType;
import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
+import org.codehaus.groovy.util.CharSequenceReader;
import java.io.BufferedWriter;
import java.io.File;
@@ -40,6 +41,7 @@ import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -47,6 +49,7 @@ import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.StringTokenizer;
+import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -69,36 +72,6 @@ import static org.codehaus.groovy.runtime.DefaultGroovyMethods.join;
* at the Java method call level. I.e. future versions of Groovy may
* remove or move a method call in this file but would normally
* aim to keep the method available from within Groovy.
- *
- * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
- * @author Jeremy Rayner
- * @author Sam Pullara
- * @author Rod Cope
- * @author Guillaume Laforge
- * @author John Wilson
- * @author Hein Meling
- * @author Dierk Koenig
- * @author Pilho Kim
- * @author Marc Guillemot
- * @author Russel Winder
- * @author bing ran
- * @author Jochen Theodorou
- * @author Paul King
- * @author Michael Baehr
- * @author Joachim Baumann
- * @author Alex Tkachman
- * @author Ted Naleid
- * @author Brad Long
- * @author Jim Jagielski
- * @author Rodolfo Velasco
- * @author jeremi Joslin
- * @author Hamlet D'Arcy
- * @author Cedric Champeau
- * @author Tim Yates
- * @author Dinko Srkoc
- * @author Pascal Lombard
- * @author Christophe Charles
- * @author Andres Almiray
*/
public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
@@ -339,15 +312,14 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
* @since 1.8.2
*/
public static String center(CharSequence self, Number numberOfChars, CharSequence padding) {
- String padding1 = padding.toString();
int numChars = numberOfChars.intValue();
if (numChars <= self.length()) {
return self.toString();
} else {
int charsToAdd = numChars - self.length();
String semiPad = charsToAdd % 2 == 1 ?
- getPadding(padding1, charsToAdd / 2 + 1) :
- getPadding(padding1, charsToAdd / 2);
+ getPadding(padding, charsToAdd / 2 + 1) :
+ getPadding(padding, charsToAdd / 2);
if (charsToAdd % 2 == 0)
return semiPad + self + semiPad;
else
@@ -628,6 +600,19 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
}
}
+ private static final class LineIterable implements Iterable<String> {
+ private final CharSequence delegate;
+
+ public LineIterable(CharSequence cs) {
+ this.delegate = cs;
+ }
+
+ @Override
+ public Iterator<String> iterator() {
+ return IOGroovyMethods.iterator(new CharSequenceReader(delegate));
+ }
+ }
+
/**
* Iterates through this CharSequence line by line. Each line is passed
* to the given 1 or 2 arg closure. If a 2 arg closure is found
@@ -660,7 +645,7 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
public static <T> T eachLine(CharSequence self, int firstLine, @ClosureParams(value=FromString.class, options={"String","String,Integer"}) Closure<T> closure) throws IOException {
int count = firstLine;
T result = null;
- for (String line : readLines((CharSequence)self.toString())) {
+ for (String line : new LineIterable(self)) {
result = callClosureForLine(closure, line, count);
count++;
}
@@ -822,22 +807,17 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
* @since 1.8.2
*/
public static String expand(CharSequence self, int tabStop) {
- if (self.length() == 0) return self.toString();
- try {
- StringBuilder builder = new StringBuilder();
- for (String line : readLines(self)) {
- builder.append(expandLine((CharSequence)line, tabStop));
- builder.append("\n");
- }
- // remove the normalized ending line ending if it was not present
- if (self.charAt(self.length() - 1) != '\n') {
- builder.deleteCharAt(builder.length() - 1);
- }
- return builder.toString();
- } catch (IOException e) {
- /* ignore */
+ if (self.length() == 0) return "";
+ StringBuilder builder = new StringBuilder();
+ for (String line : new LineIterable(self)) {
+ builder.append(expandLine((CharSequence)line, tabStop));
+ builder.append("\n");
}
- return self.toString();
+ // remove the normalized ending line ending if it was not present
+ if (self.charAt(self.length() - 1) != '\n') {
+ builder.deleteCharAt(builder.length() - 1);
+ }
+ return builder.toString();
}
/**
@@ -3126,16 +3106,12 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
public static String stripIndent(CharSequence self) {
if (self.length() == 0) return self.toString();
int runningCount = -1;
- try {
- for (String line : readLines(self)) {
- // don't take blank lines into account for calculating the indent
- if (isAllWhitespace((CharSequence) line)) continue;
- if (runningCount == -1) runningCount = line.length();
- runningCount = findMinimumLeadingSpaces(line, runningCount);
- if (runningCount == 0) break;
- }
- } catch (IOException e) {
- /* ignore */
+ for (String line : new LineIterable(self)) {
+ // don't take blank lines into account for calculating the indent
+ if (isAllWhitespace((CharSequence) line)) continue;
+ if (runningCount == -1) runningCount = line.length();
+ runningCount = findMinimumLeadingSpaces(line, runningCount);
+ if (runningCount == 0) break;
}
return stripIndent(self, runningCount == -1 ? 0 : runningCount);
}
@@ -3154,25 +3130,20 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
*/
public static String stripIndent(CharSequence self, int numChars) {
if (self.length() == 0 || numChars <= 0) return self.toString();
- try {
- StringBuilder builder = new StringBuilder();
- for (String line : readLines(self)) {
- // normalize an empty or whitespace line to \n
- // or strip the indent for lines containing non-space characters
- if (!isAllWhitespace((CharSequence) line)) {
- builder.append(stripIndentFromLine(line, numChars));
- }
- builder.append("\n");
+ StringBuilder builder = new StringBuilder();
+ for (String line : new LineIterable(self)) {
+ // normalize an empty or whitespace line to \n
+ // or strip the indent for lines containing non-space characters
+ if (!isAllWhitespace((CharSequence) line)) {
+ builder.append(stripIndentFromLine(line, numChars));
}
- // remove the normalized ending line ending if it was not present
- if (self.charAt(self.length() - 1) != '\n') {
- builder.deleteCharAt(builder.length() - 1);
- }
- return builder.toString();
- } catch (IOException e) {
- /* ignore */
+ builder.append("\n");
}
- return self.toString();
+ // remove the normalized ending line ending if it was not present
+ if (self.charAt(self.length() - 1) != '\n') {
+ builder.deleteCharAt(builder.length() - 1);
+ }
+ return builder.toString();
}
/**
@@ -3234,21 +3205,16 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
*/
public static String stripMargin(CharSequence self, char marginChar) {
if (self.length() == 0) return self.toString();
- try {
- StringBuilder builder = new StringBuilder();
- for (String line : readLines(self)) {
- builder.append(stripMarginFromLine(line, marginChar));
- builder.append("\n");
- }
- // remove the normalized ending line ending if it was not present
- if (self.charAt(self.length() - 1) != '\n') {
- builder.deleteCharAt(builder.length() - 1);
- }
- return builder.toString();
- } catch (IOException e) {
- /* ignore */
+ StringBuilder builder = new StringBuilder();
+ for (String line : new LineIterable(self)) {
+ builder.append(stripMarginFromLine(line, marginChar));
+ builder.append("\n");
}
- return self.toString();
+ // remove the normalized ending line ending if it was not present
+ if (self.charAt(self.length() - 1) != '\n') {
+ builder.deleteCharAt(builder.length() - 1);
+ }
+ return builder.toString();
}
/**
http://git-wip-us.apache.org/repos/asf/groovy/blob/35b5f345/src/main/org/codehaus/groovy/util/CharSequenceReader.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/util/CharSequenceReader.java b/src/main/org/codehaus/groovy/util/CharSequenceReader.java
new file mode 100644
index 0000000..2154002
--- /dev/null
+++ b/src/main/org/codehaus/groovy/util/CharSequenceReader.java
@@ -0,0 +1,170 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.codehaus.groovy.util;
+
+import java.io.Reader;
+import java.io.Serializable;
+
+/**
+ * {@link Reader} implementation that can read from String, StringBuffer,
+ * StringBuilder, CharBuffer or GString.
+ * <p>
+ * <strong>Note:</strong> Supports {@link #mark(int)} and {@link #reset()}.
+ */
+public class CharSequenceReader extends Reader implements Serializable {
+ /*
+ NOTE: nearly 100% borrowed from Commons-IO but we don't want to bring
+ in that whole package just yet. We need to consider reworking all of our
+ IO in light of Java 8 streams and decide whether it makes sense to bring
+ in an external package.
+ */
+ private static final long serialVersionUID = -6661279371843310693L;
+ private final CharSequence charSequence;
+ private int idx;
+ private int mark;
+ private static final int EOF = -1;
+
+ /**
+ * Construct a new instance with the specified character sequence.
+ *
+ * @param charSequence The character sequence, may be {@code null}
+ */
+ public CharSequenceReader(final CharSequence charSequence) {
+ this.charSequence = charSequence != null ? charSequence : "";
+ }
+
+ /**
+ * Close resets the reader back to the start and removes any marked position.
+ */
+ @Override
+ public void close() {
+ idx = 0;
+ mark = 0;
+ }
+
+ /**
+ * Mark the current position.
+ *
+ * @param readAheadLimit ignored
+ */
+ @Override
+ public void mark(final int readAheadLimit) {
+ mark = idx;
+ }
+
+ /**
+ * Mark is supported (returns true).
+ *
+ * @return {@code true}
+ */
+ @Override
+ public boolean markSupported() {
+ return true;
+ }
+
+ /**
+ * Read a single character.
+ *
+ * @return the next character from the character sequence
+ * or -1 if the end has been reached.
+ */
+ @Override
+ public int read() {
+ if (idx >= charSequence.length()) {
+ return EOF;
+ } else {
+ return charSequence.charAt(idx++);
+ }
+ }
+
+ /**
+ * Read the sepcified number of characters into the array.
+ *
+ * @param array The array to store the characters in
+ * @param offset The starting position in the array to store
+ * @param length The maximum number of characters to read
+ * @return The number of characters read or -1 if there are
+ * no more
+ */
+ @Override
+ public int read(final char[] array, final int offset, final int length) {
+ if (idx >= charSequence.length()) {
+ return EOF;
+ }
+ if (array == null) {
+ throw new NullPointerException("Character array is missing");
+ }
+ if (length < 0 || offset < 0 || offset + length > array.length) {
+ throw new IndexOutOfBoundsException("Array Size=" + array.length +
+ ", offset=" + offset + ", length=" + length);
+ }
+ int count = 0;
+ for (int i = 0; i < length; i++) {
+ final int c = read();
+ if (c == EOF) {
+ return count;
+ }
+ array[offset + i] = (char)c;
+ count++;
+ }
+ return count;
+ }
+
+ /**
+ * Reset the reader to the last marked position (or the beginning if
+ * mark has not been called).
+ */
+ @Override
+ public void reset() {
+ idx = mark;
+ }
+
+ /**
+ * Skip the specified number of characters.
+ *
+ * @param n The number of characters to skip
+ * @return The actual number of characters skipped
+ */
+ @Override
+ public long skip(final long n) {
+ if (n < 0) {
+ throw new IllegalArgumentException(
+ "Number of characters to skip is less than zero: " + n);
+ }
+ if (idx >= charSequence.length()) {
+ return EOF;
+ }
+ final int dest = (int)Math.min(charSequence.length(), idx + n);
+ final int count = dest - idx;
+ idx = dest;
+ return count;
+ }
+
+ /**
+ * Return a String representation of the underlying
+ * character sequence.
+ *
+ * @return The contents of the character sequence
+ */
+ @Override
+ public String toString() {
+ return charSequence.toString();
+ }
+}
\ No newline at end of file