Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JDK-8302323 Add repeat methods to StringBuilder/StringBuffer #12728

Closed
wants to merge 14 commits into from
68 changes: 24 additions & 44 deletions src/java.base/share/classes/java/lang/AbstractStringBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -1834,52 +1834,31 @@ private final void appendChars(CharSequence s, int off, int end) {
*
* @since 21
JimLaskey marked this conversation as resolved.
Show resolved Hide resolved
* @throws IllegalArgumentException if {@code count} is less than zero
* @throws StringIndexOutOfBoundsException if the result overflows the buffer
* @throws IndexOutOfBoundsException if the result overflows the buffer
JimLaskey marked this conversation as resolved.
Show resolved Hide resolved
*/
public AbstractStringBuilder repeat(char c, int count) {
JimLaskey marked this conversation as resolved.
Show resolved Hide resolved
if (count < 0) {
throw new IllegalArgumentException("count is less than zero: " + count);
}
if (count == 0) {
} else if (count == 0) {
return this;
}
ensureCapacityInternal(this.count + count);
if (isLatin1() && StringLatin1.canEncode(c)) {
int index = this.count;
while (count-- != 0) {
value[index++] = (byte) c;
int index = this.count;
int limit = index + count;
boolean isLatin1 = isLatin1();
if (isLatin1 && StringLatin1.canEncode(c)) {
while (index < limit) {
JimLaskey marked this conversation as resolved.
Show resolved Hide resolved
value[index++] = (byte)c;
}
JimLaskey marked this conversation as resolved.
Show resolved Hide resolved
this.count = index;
} else {
if (isLatin1()) {
if (isLatin1) {
inflate();
}
int index = this.count;
while (count-- != 0) {
while (index < limit) {
StringUTF16.putCharSB(value, index++, c);
}
this.count = index;
}
return this;
}

private AbstractStringBuilder repeatNull(int count) {
if (count < 0) {
throw new IllegalArgumentException("count is less than zero: " + count);
} else if (count == 0) {
return this;
}
int offset = this.count;
appendNull();
int length = this.count - offset;
int valueLength = length << coder;
if ((Integer.MAX_VALUE - offset) / count < valueLength) {
throw new OutOfMemoryError("Required length exceeds implementation limit");
}
int limit = count * length;
ensureCapacityInternal(offset + limit);
String.repeatCopyRest(value, offset << coder, limit << coder, length << coder);
this.count = offset + limit;
this.count = limit;
return this;
}

Expand All @@ -1897,39 +1876,40 @@ private AbstractStringBuilder repeatNull(int count) {
*
* @since 21
* @throws IllegalArgumentException if {@code count} is less than zero
* @throws StringIndexOutOfBoundsException if the result overflows the buffer
* @throws IndexOutOfBoundsException if the result overflows the buffer
JimLaskey marked this conversation as resolved.
Show resolved Hide resolved
*/
public AbstractStringBuilder repeat(CharSequence cs, int count) {
if (cs == null) {
return repeatNull(count);
} else if (count < 0) {
if (count < 0) {
throw new IllegalArgumentException("count is less than zero: " + count);
} else if (count == 0) {
return this;
} else if (count == 1) {
return append(cs);
}

if (cs == null) {
cs = "null";
}
int length = cs.length();
if (length == 1) {
JimLaskey marked this conversation as resolved.
Show resolved Hide resolved
return repeat(cs.charAt(0), count);
}
int valueLength = length << UTF16;
if ((Integer.MAX_VALUE - this.count) / count < valueLength) {
int offset = this.count;
int valueLength = length << coder;
if ((Integer.MAX_VALUE - offset) / count < valueLength) {
throw new OutOfMemoryError("Required length exceeds implementation limit");
}
int limit = count * length;
int offset = this.count;
ensureCapacityInternal(offset + limit);
int total = count * length;
JimLaskey marked this conversation as resolved.
Show resolved Hide resolved
int limit = offset + total;
ensureCapacityInternal(limit);
JimLaskey marked this conversation as resolved.
Show resolved Hide resolved
if (cs instanceof String str) {
putStringAt(offset, str);
} else if (cs instanceof AbstractStringBuilder asb) {
JimLaskey marked this conversation as resolved.
Show resolved Hide resolved
append(asb);
} else {
appendChars(cs, 0, length);
}
String.repeatCopyRest(value, offset << coder, limit << coder, length << coder);
this.count = offset + limit;
String.repeatCopyRest(value, offset << coder, total << coder, length << coder);
this.count = limit;
return this;
}
}
4 changes: 2 additions & 2 deletions src/java.base/share/classes/java/lang/StringBuffer.java
Original file line number Diff line number Diff line change
Expand Up @@ -711,7 +711,7 @@ public synchronized StringBuffer reverse() {
/**
* @since 21
* @throws IllegalArgumentException {@inheritDoc}
JimLaskey marked this conversation as resolved.
Show resolved Hide resolved
* @throws StringIndexOutOfBoundsException {@inheritDoc}
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
@Override
public synchronized StringBuffer repeat(char c, int count) {
Expand All @@ -722,7 +722,7 @@ public synchronized StringBuffer repeat(char c, int count) {
/**
* @since 21
* @throws IllegalArgumentException {@inheritDoc}
* @throws StringIndexOutOfBoundsException {@inheritDoc}
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
@Override
public synchronized StringBuffer repeat(CharSequence cs, int count) {
Expand Down
4 changes: 2 additions & 2 deletions src/java.base/share/classes/java/lang/StringBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ public StringBuilder reverse() {
/**
* @since 21
* @throws IllegalArgumentException {@inheritDoc}
* @throws StringIndexOutOfBoundsException {@inheritDoc}
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
@Override
public StringBuilder repeat(char c, int count) {
Expand All @@ -460,7 +460,7 @@ public StringBuilder repeat(char c, int count) {
/**
* @since 21
* @throws IllegalArgumentException {@inheritDoc}
* @throws StringIndexOutOfBoundsException {@inheritDoc}
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
@Override
public StringBuilder repeat(CharSequence cs, int count) {
Expand Down
12 changes: 6 additions & 6 deletions test/jdk/java/lang/StringBuilder/Repeat.java
Original file line number Diff line number Diff line change
Expand Up @@ -116,42 +116,42 @@ public void exceptions() {
try {
sb.repeat(' ', Integer.MAX_VALUE);
throw new RuntimeException("No OutOfMemoryError thrown");
} catch (OutOfMemoryError | StringIndexOutOfBoundsException ex) {
} catch (OutOfMemoryError | IndexOutOfBoundsException ex) {
// Okay
}

try {
sb.repeat(" ", Integer.MAX_VALUE);
throw new RuntimeException("No OutOfMemoryError thrown");
} catch (OutOfMemoryError | StringIndexOutOfBoundsException ex) {
} catch (OutOfMemoryError | IndexOutOfBoundsException ex) {
// Okay
}

try {
sb.repeat(MYCHARS, Integer.MAX_VALUE);
throw new RuntimeException("No OutOfMemoryError thrown");
} catch (OutOfMemoryError | StringIndexOutOfBoundsException ex) {
} catch (OutOfMemoryError | IndexOutOfBoundsException ex) {
// Okay
}

try {
sb.repeat(' ', -1);
throw new RuntimeException("No IllegalArgumentException thrown");
} catch (IllegalArgumentException | StringIndexOutOfBoundsException ex) {
} catch (IllegalArgumentException | IndexOutOfBoundsException ex) {
// Okay
}

try {
sb.repeat("abc", -1);
throw new RuntimeException("No IllegalArgumentException thrown");
} catch (IllegalArgumentException | StringIndexOutOfBoundsException ex) {
} catch (IllegalArgumentException | IndexOutOfBoundsException ex) {
// Okay
}

try {
sb.repeat(MYCHARS, -1);
throw new RuntimeException("No IllegalArgumentException thrown");
} catch (IllegalArgumentException | StringIndexOutOfBoundsException ex) {
} catch (IllegalArgumentException | IndexOutOfBoundsException ex) {
// Okay
}

Expand Down