8039124: j.u.regex.Matcher.appendReplace/Tail() should support StringBuilder variant
To add the StringBuilder variant Co-authored-by: Peter Levart <peter.levart@gmail.com> Reviewed-by: alanb, sherman
This commit is contained in:
parent
2f501cd8a5
commit
55d8dc5d85
@ -65,9 +65,10 @@ import java.util.Objects;
|
||||
* new strings whose contents can, if desired, be computed from the match
|
||||
* result. The {@link #appendReplacement appendReplacement} and {@link
|
||||
* #appendTail appendTail} methods can be used in tandem in order to collect
|
||||
* the result into an existing string buffer, or the more convenient {@link
|
||||
* #replaceAll replaceAll} method can be used to create a string in which every
|
||||
* matching subsequence in the input sequence is replaced.
|
||||
* the result into an existing string buffer or string builder. Alternatively,
|
||||
* the more convenient {@link #replaceAll replaceAll} method can be used to
|
||||
* create a string in which every matching subsequence in the input sequence
|
||||
* is replaced.
|
||||
*
|
||||
* <p> The explicit state of a matcher includes the start and end indices of
|
||||
* the most recent successful match. It also includes the start and end
|
||||
@ -792,15 +793,115 @@ public final class Matcher implements MatchResult {
|
||||
* that does not exist in the pattern
|
||||
*/
|
||||
public Matcher appendReplacement(StringBuffer sb, String replacement) {
|
||||
|
||||
// If no match, return error
|
||||
if (first < 0)
|
||||
throw new IllegalStateException("No match available");
|
||||
|
||||
// Process substitution string to replace group references with groups
|
||||
int cursor = 0;
|
||||
StringBuilder result = new StringBuilder();
|
||||
appendExpandedReplacement(replacement, result);
|
||||
// Append the intervening text
|
||||
sb.append(text, lastAppendPosition, first);
|
||||
// Append the match substitution
|
||||
sb.append(result);
|
||||
lastAppendPosition = last;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements a non-terminal append-and-replace step.
|
||||
*
|
||||
* <p> This method performs the following actions: </p>
|
||||
*
|
||||
* <ol>
|
||||
*
|
||||
* <li><p> It reads characters from the input sequence, starting at the
|
||||
* append position, and appends them to the given string builder. It
|
||||
* stops after reading the last character preceding the previous match,
|
||||
* that is, the character at index {@link
|
||||
* #start()} <tt>-</tt> <tt>1</tt>. </p></li>
|
||||
*
|
||||
* <li><p> It appends the given replacement string to the string builder.
|
||||
* </p></li>
|
||||
*
|
||||
* <li><p> It sets the append position of this matcher to the index of
|
||||
* the last character matched, plus one, that is, to {@link #end()}.
|
||||
* </p></li>
|
||||
*
|
||||
* </ol>
|
||||
*
|
||||
* <p> The replacement string may contain references to subsequences
|
||||
* captured during the previous match: Each occurrence of
|
||||
* <tt>$</tt><i>g</i><tt></tt> will be replaced by the result of
|
||||
* evaluating {@link #group(int) group}<tt>(</tt><i>g</i><tt>)</tt>.
|
||||
* The first number after the <tt>$</tt> is always treated as part of
|
||||
* the group reference. Subsequent numbers are incorporated into g if
|
||||
* they would form a legal group reference. Only the numerals '0'
|
||||
* through '9' are considered as potential components of the group
|
||||
* reference. If the second group matched the string <tt>"foo"</tt>, for
|
||||
* example, then passing the replacement string <tt>"$2bar"</tt> would
|
||||
* cause <tt>"foobar"</tt> to be appended to the string builder. A dollar
|
||||
* sign (<tt>$</tt>) may be included as a literal in the replacement
|
||||
* string by preceding it with a backslash (<tt>\$</tt>).
|
||||
*
|
||||
* <p> Note that backslashes (<tt>\</tt>) and dollar signs (<tt>$</tt>) in
|
||||
* the replacement string may cause the results to be different than if it
|
||||
* were being treated as a literal replacement string. Dollar signs may be
|
||||
* treated as references to captured subsequences as described above, and
|
||||
* backslashes are used to escape literal characters in the replacement
|
||||
* string.
|
||||
*
|
||||
* <p> This method is intended to be used in a loop together with the
|
||||
* {@link #appendTail appendTail} and {@link #find find} methods. The
|
||||
* following code, for example, writes <tt>one dog two dogs in the
|
||||
* yard</tt> to the standard-output stream: </p>
|
||||
*
|
||||
* <blockquote><pre>
|
||||
* Pattern p = Pattern.compile("cat");
|
||||
* Matcher m = p.matcher("one cat two cats in the yard");
|
||||
* StringBuilder sb = new StringBuilder();
|
||||
* while (m.find()) {
|
||||
* m.appendReplacement(sb, "dog");
|
||||
* }
|
||||
* m.appendTail(sb);
|
||||
* System.out.println(sb.toString());</pre></blockquote>
|
||||
*
|
||||
* @param sb
|
||||
* The target string builder
|
||||
* @param replacement
|
||||
* The replacement string
|
||||
* @return This matcher
|
||||
*
|
||||
* @throws IllegalStateException
|
||||
* If no match has yet been attempted,
|
||||
* or if the previous match operation failed
|
||||
* @throws IllegalArgumentException
|
||||
* If the replacement string refers to a named-capturing
|
||||
* group that does not exist in the pattern
|
||||
* @throws IndexOutOfBoundsException
|
||||
* If the replacement string refers to a capturing group
|
||||
* that does not exist in the pattern
|
||||
* @since 1.9
|
||||
*/
|
||||
public Matcher appendReplacement(StringBuilder sb, String replacement) {
|
||||
// If no match, return error
|
||||
if (first < 0)
|
||||
throw new IllegalStateException("No match available");
|
||||
StringBuilder result = new StringBuilder();
|
||||
appendExpandedReplacement(replacement, result);
|
||||
// Append the intervening text
|
||||
sb.append(text, lastAppendPosition, first);
|
||||
// Append the match substitution
|
||||
sb.append(result);
|
||||
lastAppendPosition = last;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes replacement string to replace group references with
|
||||
* groups.
|
||||
*/
|
||||
private StringBuilder appendExpandedReplacement(
|
||||
String replacement, StringBuilder result) {
|
||||
int cursor = 0;
|
||||
while (cursor < replacement.length()) {
|
||||
char nextChar = replacement.charAt(cursor);
|
||||
if (nextChar == '\\') {
|
||||
@ -852,7 +953,7 @@ public final class Matcher implements MatchResult {
|
||||
cursor++;
|
||||
} else {
|
||||
// The first number is always a group
|
||||
refNum = (int)nextChar - '0';
|
||||
refNum = nextChar - '0';
|
||||
if ((refNum < 0) || (refNum > 9))
|
||||
throw new IllegalArgumentException(
|
||||
"Illegal group reference");
|
||||
@ -884,13 +985,7 @@ public final class Matcher implements MatchResult {
|
||||
cursor++;
|
||||
}
|
||||
}
|
||||
// Append the intervening text
|
||||
sb.append(text, lastAppendPosition, first);
|
||||
// Append the match substitution
|
||||
sb.append(result);
|
||||
|
||||
lastAppendPosition = last;
|
||||
return this;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -912,6 +1007,27 @@ public final class Matcher implements MatchResult {
|
||||
return sb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements a terminal append-and-replace step.
|
||||
*
|
||||
* <p> This method reads characters from the input sequence, starting at
|
||||
* the append position, and appends them to the given string builder. It is
|
||||
* intended to be invoked after one or more invocations of the {@link
|
||||
* #appendReplacement appendReplacement} method in order to copy the
|
||||
* remainder of the input sequence. </p>
|
||||
*
|
||||
* @param sb
|
||||
* The target string builder
|
||||
*
|
||||
* @return The target string builder
|
||||
*
|
||||
* @since 1.9
|
||||
*/
|
||||
public StringBuilder appendTail(StringBuilder sb) {
|
||||
sb.append(text, lastAppendPosition, getTextLength());
|
||||
return sb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces every subsequence of the input sequence that matches the
|
||||
* pattern with the given replacement string.
|
||||
@ -950,7 +1066,7 @@ public final class Matcher implements MatchResult {
|
||||
reset();
|
||||
boolean result = find();
|
||||
if (result) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
do {
|
||||
appendReplacement(sb, replacement);
|
||||
result = find();
|
||||
@ -1000,7 +1116,7 @@ public final class Matcher implements MatchResult {
|
||||
reset();
|
||||
if (!find())
|
||||
return text.toString();
|
||||
StringBuffer sb = new StringBuffer();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
appendReplacement(sb, replacement);
|
||||
appendTail(sb);
|
||||
return sb.toString();
|
||||
|
@ -32,7 +32,7 @@
|
||||
* 6358731 6178785 6284152 6231989 6497148 6486934 6233084 6504326 6635133
|
||||
* 6350801 6676425 6878475 6919132 6931676 6948903 6990617 7014645 7039066
|
||||
* 7067045 7014640 7189363 8007395 8013252 8013254 8012646 8023647 6559590
|
||||
* 8027645 8035076
|
||||
* 8027645 8035076 8039124
|
||||
*/
|
||||
|
||||
import java.util.regex.*;
|
||||
@ -75,7 +75,10 @@ public class RegExTest {
|
||||
// Substitition tests on randomly generated sequences
|
||||
globalSubstitute();
|
||||
stringbufferSubstitute();
|
||||
stringbuilderSubstitute();
|
||||
|
||||
substitutionBasher();
|
||||
substitutionBasher2();
|
||||
|
||||
// Canonical Equivalence
|
||||
ceTest();
|
||||
@ -296,10 +299,12 @@ public class RegExTest {
|
||||
|
||||
final Matcher m = Pattern.compile("xyz").matcher("xyz");
|
||||
m.matches();
|
||||
check(new Runnable() { public void run() { m.appendTail(null);}});
|
||||
check(new Runnable() { public void run() { m.appendTail((StringBuffer)null);}});
|
||||
check(new Runnable() { public void run() { m.appendTail((StringBuilder)null);}});
|
||||
check(new Runnable() { public void run() { m.replaceAll(null);}});
|
||||
check(new Runnable() { public void run() { m.replaceFirst(null);}});
|
||||
check(new Runnable() { public void run() { m.appendReplacement(null, null);}});
|
||||
check(new Runnable() { public void run() { m.appendReplacement((StringBuffer)null, null);}});
|
||||
check(new Runnable() { public void run() { m.appendReplacement((StringBuilder)null, null);}});
|
||||
check(new Runnable() { public void run() { m.reset(null);}});
|
||||
check(new Runnable() { public void run() { Matcher.quoteReplacement(null);}});
|
||||
//check(new Runnable() { public void run() { m.usePattern(null);}});
|
||||
@ -2973,6 +2978,286 @@ public class RegExTest {
|
||||
report("SB Substitution");
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the usage of Matcher.appendReplacement() with literal
|
||||
* and group substitutions.
|
||||
*/
|
||||
private static void stringbuilderSubstitute() throws Exception {
|
||||
// SB substitution with literal
|
||||
String blah = "zzzblahzzz";
|
||||
Pattern p = Pattern.compile("blah");
|
||||
Matcher m = p.matcher(blah);
|
||||
StringBuilder result = new StringBuilder();
|
||||
try {
|
||||
m.appendReplacement(result, "blech");
|
||||
failCount++;
|
||||
} catch (IllegalStateException e) {
|
||||
}
|
||||
m.find();
|
||||
m.appendReplacement(result, "blech");
|
||||
if (!result.toString().equals("zzzblech"))
|
||||
failCount++;
|
||||
|
||||
m.appendTail(result);
|
||||
if (!result.toString().equals("zzzblechzzz"))
|
||||
failCount++;
|
||||
|
||||
// SB substitution with groups
|
||||
blah = "zzzabcdzzz";
|
||||
p = Pattern.compile("(ab)(cd)*");
|
||||
m = p.matcher(blah);
|
||||
result = new StringBuilder();
|
||||
try {
|
||||
m.appendReplacement(result, "$1");
|
||||
failCount++;
|
||||
} catch (IllegalStateException e) {
|
||||
}
|
||||
m.find();
|
||||
m.appendReplacement(result, "$1");
|
||||
if (!result.toString().equals("zzzab"))
|
||||
failCount++;
|
||||
|
||||
m.appendTail(result);
|
||||
if (!result.toString().equals("zzzabzzz"))
|
||||
failCount++;
|
||||
|
||||
// SB substitution with 3 groups
|
||||
blah = "zzzabcdcdefzzz";
|
||||
p = Pattern.compile("(ab)(cd)*(ef)");
|
||||
m = p.matcher(blah);
|
||||
result = new StringBuilder();
|
||||
try {
|
||||
m.appendReplacement(result, "$1w$2w$3");
|
||||
failCount++;
|
||||
} catch (IllegalStateException e) {
|
||||
}
|
||||
m.find();
|
||||
m.appendReplacement(result, "$1w$2w$3");
|
||||
if (!result.toString().equals("zzzabwcdwef"))
|
||||
failCount++;
|
||||
|
||||
m.appendTail(result);
|
||||
if (!result.toString().equals("zzzabwcdwefzzz"))
|
||||
failCount++;
|
||||
|
||||
// SB substitution with groups and three matches
|
||||
// skipping middle match
|
||||
blah = "zzzabcdzzzabcddzzzabcdzzz";
|
||||
p = Pattern.compile("(ab)(cd*)");
|
||||
m = p.matcher(blah);
|
||||
result = new StringBuilder();
|
||||
try {
|
||||
m.appendReplacement(result, "$1");
|
||||
failCount++;
|
||||
} catch (IllegalStateException e) {
|
||||
}
|
||||
m.find();
|
||||
m.appendReplacement(result, "$1");
|
||||
if (!result.toString().equals("zzzab"))
|
||||
failCount++;
|
||||
|
||||
m.find();
|
||||
m.find();
|
||||
m.appendReplacement(result, "$2");
|
||||
if (!result.toString().equals("zzzabzzzabcddzzzcd"))
|
||||
failCount++;
|
||||
|
||||
m.appendTail(result);
|
||||
if (!result.toString().equals("zzzabzzzabcddzzzcdzzz"))
|
||||
failCount++;
|
||||
|
||||
// Check to make sure escaped $ is ignored
|
||||
blah = "zzzabcdcdefzzz";
|
||||
p = Pattern.compile("(ab)(cd)*(ef)");
|
||||
m = p.matcher(blah);
|
||||
result = new StringBuilder();
|
||||
m.find();
|
||||
m.appendReplacement(result, "$1w\\$2w$3");
|
||||
if (!result.toString().equals("zzzabw$2wef"))
|
||||
failCount++;
|
||||
|
||||
m.appendTail(result);
|
||||
if (!result.toString().equals("zzzabw$2wefzzz"))
|
||||
failCount++;
|
||||
|
||||
// Check to make sure a reference to nonexistent group causes error
|
||||
blah = "zzzabcdcdefzzz";
|
||||
p = Pattern.compile("(ab)(cd)*(ef)");
|
||||
m = p.matcher(blah);
|
||||
result = new StringBuilder();
|
||||
m.find();
|
||||
try {
|
||||
m.appendReplacement(result, "$1w$5w$3");
|
||||
failCount++;
|
||||
} catch (IndexOutOfBoundsException ioobe) {
|
||||
// Correct result
|
||||
}
|
||||
|
||||
// Check double digit group references
|
||||
blah = "zzz123456789101112zzz";
|
||||
p = Pattern.compile("(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)(11)");
|
||||
m = p.matcher(blah);
|
||||
result = new StringBuilder();
|
||||
m.find();
|
||||
m.appendReplacement(result, "$1w$11w$3");
|
||||
if (!result.toString().equals("zzz1w11w3"))
|
||||
failCount++;
|
||||
|
||||
// Check to make sure it backs off $15 to $1 if only three groups
|
||||
blah = "zzzabcdcdefzzz";
|
||||
p = Pattern.compile("(ab)(cd)*(ef)");
|
||||
m = p.matcher(blah);
|
||||
result = new StringBuilder();
|
||||
m.find();
|
||||
m.appendReplacement(result, "$1w$15w$3");
|
||||
if (!result.toString().equals("zzzabwab5wef"))
|
||||
failCount++;
|
||||
|
||||
|
||||
// Supplementary character test
|
||||
// SB substitution with literal
|
||||
blah = toSupplementaries("zzzblahzzz");
|
||||
p = Pattern.compile(toSupplementaries("blah"));
|
||||
m = p.matcher(blah);
|
||||
result = new StringBuilder();
|
||||
try {
|
||||
m.appendReplacement(result, toSupplementaries("blech"));
|
||||
failCount++;
|
||||
} catch (IllegalStateException e) {
|
||||
}
|
||||
m.find();
|
||||
m.appendReplacement(result, toSupplementaries("blech"));
|
||||
if (!result.toString().equals(toSupplementaries("zzzblech")))
|
||||
failCount++;
|
||||
m.appendTail(result);
|
||||
if (!result.toString().equals(toSupplementaries("zzzblechzzz")))
|
||||
failCount++;
|
||||
|
||||
// SB substitution with groups
|
||||
blah = toSupplementaries("zzzabcdzzz");
|
||||
p = Pattern.compile(toSupplementaries("(ab)(cd)*"));
|
||||
m = p.matcher(blah);
|
||||
result = new StringBuilder();
|
||||
try {
|
||||
m.appendReplacement(result, "$1");
|
||||
failCount++;
|
||||
} catch (IllegalStateException e) {
|
||||
}
|
||||
m.find();
|
||||
m.appendReplacement(result, "$1");
|
||||
if (!result.toString().equals(toSupplementaries("zzzab")))
|
||||
failCount++;
|
||||
|
||||
m.appendTail(result);
|
||||
if (!result.toString().equals(toSupplementaries("zzzabzzz")))
|
||||
failCount++;
|
||||
|
||||
// SB substitution with 3 groups
|
||||
blah = toSupplementaries("zzzabcdcdefzzz");
|
||||
p = Pattern.compile(toSupplementaries("(ab)(cd)*(ef)"));
|
||||
m = p.matcher(blah);
|
||||
result = new StringBuilder();
|
||||
try {
|
||||
m.appendReplacement(result, toSupplementaries("$1w$2w$3"));
|
||||
failCount++;
|
||||
} catch (IllegalStateException e) {
|
||||
}
|
||||
m.find();
|
||||
m.appendReplacement(result, toSupplementaries("$1w$2w$3"));
|
||||
if (!result.toString().equals(toSupplementaries("zzzabwcdwef")))
|
||||
failCount++;
|
||||
|
||||
m.appendTail(result);
|
||||
if (!result.toString().equals(toSupplementaries("zzzabwcdwefzzz")))
|
||||
failCount++;
|
||||
|
||||
// SB substitution with groups and three matches
|
||||
// skipping middle match
|
||||
blah = toSupplementaries("zzzabcdzzzabcddzzzabcdzzz");
|
||||
p = Pattern.compile(toSupplementaries("(ab)(cd*)"));
|
||||
m = p.matcher(blah);
|
||||
result = new StringBuilder();
|
||||
try {
|
||||
m.appendReplacement(result, "$1");
|
||||
failCount++;
|
||||
} catch (IllegalStateException e) {
|
||||
}
|
||||
m.find();
|
||||
m.appendReplacement(result, "$1");
|
||||
if (!result.toString().equals(toSupplementaries("zzzab")))
|
||||
failCount++;
|
||||
|
||||
m.find();
|
||||
m.find();
|
||||
m.appendReplacement(result, "$2");
|
||||
if (!result.toString().equals(toSupplementaries("zzzabzzzabcddzzzcd")))
|
||||
failCount++;
|
||||
|
||||
m.appendTail(result);
|
||||
if (!result.toString().equals(toSupplementaries("zzzabzzzabcddzzzcdzzz")))
|
||||
failCount++;
|
||||
|
||||
// Check to make sure escaped $ is ignored
|
||||
blah = toSupplementaries("zzzabcdcdefzzz");
|
||||
p = Pattern.compile(toSupplementaries("(ab)(cd)*(ef)"));
|
||||
m = p.matcher(blah);
|
||||
result = new StringBuilder();
|
||||
m.find();
|
||||
m.appendReplacement(result, toSupplementaries("$1w\\$2w$3"));
|
||||
if (!result.toString().equals(toSupplementaries("zzzabw$2wef")))
|
||||
failCount++;
|
||||
|
||||
m.appendTail(result);
|
||||
if (!result.toString().equals(toSupplementaries("zzzabw$2wefzzz")))
|
||||
failCount++;
|
||||
|
||||
// Check to make sure a reference to nonexistent group causes error
|
||||
blah = toSupplementaries("zzzabcdcdefzzz");
|
||||
p = Pattern.compile(toSupplementaries("(ab)(cd)*(ef)"));
|
||||
m = p.matcher(blah);
|
||||
result = new StringBuilder();
|
||||
m.find();
|
||||
try {
|
||||
m.appendReplacement(result, toSupplementaries("$1w$5w$3"));
|
||||
failCount++;
|
||||
} catch (IndexOutOfBoundsException ioobe) {
|
||||
// Correct result
|
||||
}
|
||||
// Check double digit group references
|
||||
blah = toSupplementaries("zzz123456789101112zzz");
|
||||
p = Pattern.compile("(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)(11)");
|
||||
m = p.matcher(blah);
|
||||
result = new StringBuilder();
|
||||
m.find();
|
||||
m.appendReplacement(result, toSupplementaries("$1w$11w$3"));
|
||||
if (!result.toString().equals(toSupplementaries("zzz1w11w3")))
|
||||
failCount++;
|
||||
|
||||
// Check to make sure it backs off $15 to $1 if only three groups
|
||||
blah = toSupplementaries("zzzabcdcdefzzz");
|
||||
p = Pattern.compile(toSupplementaries("(ab)(cd)*(ef)"));
|
||||
m = p.matcher(blah);
|
||||
result = new StringBuilder();
|
||||
m.find();
|
||||
m.appendReplacement(result, toSupplementaries("$1w$15w$3"));
|
||||
if (!result.toString().equals(toSupplementaries("zzzabwab5wef")))
|
||||
failCount++;
|
||||
// Check nothing has been appended into the output buffer if
|
||||
// the replacement string triggers IllegalArgumentException.
|
||||
p = Pattern.compile("(abc)");
|
||||
m = p.matcher("abcd");
|
||||
result = new StringBuilder();
|
||||
m.find();
|
||||
try {
|
||||
m.appendReplacement(result, ("xyz$g"));
|
||||
failCount++;
|
||||
} catch (IllegalArgumentException iae) {
|
||||
if (result.length() != 0)
|
||||
failCount++;
|
||||
}
|
||||
report("SB Substitution 2");
|
||||
}
|
||||
|
||||
/*
|
||||
* 5 groups of characters are created to make a substitution string.
|
||||
* A base string will be created including random lead chars, the
|
||||
@ -3059,6 +3344,93 @@ public class RegExTest {
|
||||
report("Substitution Basher");
|
||||
}
|
||||
|
||||
/*
|
||||
* 5 groups of characters are created to make a substitution string.
|
||||
* A base string will be created including random lead chars, the
|
||||
* substitution string, and random trailing chars.
|
||||
* A pattern containing the 5 groups is searched for and replaced with:
|
||||
* random group + random string + random group.
|
||||
* The results are checked for correctness.
|
||||
*/
|
||||
private static void substitutionBasher2() {
|
||||
for (int runs = 0; runs<1000; runs++) {
|
||||
// Create a base string to work in
|
||||
int leadingChars = generator.nextInt(10);
|
||||
StringBuilder baseBuffer = new StringBuilder(100);
|
||||
String leadingString = getRandomAlphaString(leadingChars);
|
||||
baseBuffer.append(leadingString);
|
||||
|
||||
// Create 5 groups of random number of random chars
|
||||
// Create the string to substitute
|
||||
// Create the pattern string to search for
|
||||
StringBuilder bufferToSub = new StringBuilder(25);
|
||||
StringBuilder bufferToPat = new StringBuilder(50);
|
||||
String[] groups = new String[5];
|
||||
for(int i=0; i<5; i++) {
|
||||
int aGroupSize = generator.nextInt(5)+1;
|
||||
groups[i] = getRandomAlphaString(aGroupSize);
|
||||
bufferToSub.append(groups[i]);
|
||||
bufferToPat.append('(');
|
||||
bufferToPat.append(groups[i]);
|
||||
bufferToPat.append(')');
|
||||
}
|
||||
String stringToSub = bufferToSub.toString();
|
||||
String pattern = bufferToPat.toString();
|
||||
|
||||
// Place sub string into working string at random index
|
||||
baseBuffer.append(stringToSub);
|
||||
|
||||
// Append random chars to end
|
||||
int trailingChars = generator.nextInt(10);
|
||||
String trailingString = getRandomAlphaString(trailingChars);
|
||||
baseBuffer.append(trailingString);
|
||||
String baseString = baseBuffer.toString();
|
||||
|
||||
// Create test pattern and matcher
|
||||
Pattern p = Pattern.compile(pattern);
|
||||
Matcher m = p.matcher(baseString);
|
||||
|
||||
// Reject candidate if pattern happens to start early
|
||||
m.find();
|
||||
if (m.start() < leadingChars)
|
||||
continue;
|
||||
|
||||
// Reject candidate if more than one match
|
||||
if (m.find())
|
||||
continue;
|
||||
|
||||
// Construct a replacement string with :
|
||||
// random group + random string + random group
|
||||
StringBuilder bufferToRep = new StringBuilder();
|
||||
int groupIndex1 = generator.nextInt(5);
|
||||
bufferToRep.append("$" + (groupIndex1 + 1));
|
||||
String randomMidString = getRandomAlphaString(5);
|
||||
bufferToRep.append(randomMidString);
|
||||
int groupIndex2 = generator.nextInt(5);
|
||||
bufferToRep.append("$" + (groupIndex2 + 1));
|
||||
String replacement = bufferToRep.toString();
|
||||
|
||||
// Do the replacement
|
||||
String result = m.replaceAll(replacement);
|
||||
|
||||
// Construct expected result
|
||||
StringBuilder bufferToRes = new StringBuilder();
|
||||
bufferToRes.append(leadingString);
|
||||
bufferToRes.append(groups[groupIndex1]);
|
||||
bufferToRes.append(randomMidString);
|
||||
bufferToRes.append(groups[groupIndex2]);
|
||||
bufferToRes.append(trailingString);
|
||||
String expectedResult = bufferToRes.toString();
|
||||
|
||||
// Check results
|
||||
if (!result.equals(expectedResult)) {
|
||||
failCount++;
|
||||
}
|
||||
}
|
||||
|
||||
report("Substitution Basher 2");
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the handling of some escape sequences that the Pattern
|
||||
* class should process instead of the java compiler. These are
|
||||
|
Loading…
x
Reference in New Issue
Block a user