mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 07:14:30 +02:00
8222955: Optimize String.replace(CharSequence, CharSequence) for common cases
Reviewed-by: redestad, tvaleev
This commit is contained in:
parent
0c6f7e5516
commit
4f02d011b0
5 changed files with 408 additions and 34 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -42,6 +42,14 @@ import static java.lang.String.checkOffset;
|
|||
|
||||
final class StringLatin1 {
|
||||
|
||||
/**
|
||||
* The maximum size of array to allocate (unless necessary).
|
||||
* Some VMs reserve some header words in an array.
|
||||
* Attempts to allocate larger arrays may result in
|
||||
* OutOfMemoryError: Requested array size exceeds VM limit
|
||||
*/
|
||||
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
|
||||
|
||||
public static char charAt(byte[] value, int index) {
|
||||
if (index < 0 || index >= value.length) {
|
||||
throw new StringIndexOutOfBoundsException(index);
|
||||
|
@ -304,7 +312,7 @@ final class StringLatin1 {
|
|||
}
|
||||
if (i < len) {
|
||||
if (canEncode(newChar)) {
|
||||
byte buf[] = new byte[len];
|
||||
byte[] buf = StringConcatHelper.newArray(len);
|
||||
for (int j = 0; j < i; j++) { // TBD arraycopy?
|
||||
buf[j] = value[j];
|
||||
}
|
||||
|
@ -330,6 +338,64 @@ final class StringLatin1 {
|
|||
return null; // for string to return this;
|
||||
}
|
||||
|
||||
public static String replace(byte[] value, int valLen, byte[] targ,
|
||||
int targLen, byte[] repl, int replLen)
|
||||
{
|
||||
assert targLen > 0;
|
||||
int i, j, p = 0;
|
||||
if (valLen == 0 || (i = indexOf(value, valLen, targ, targLen, 0)) < 0) {
|
||||
return null; // for string to return this;
|
||||
}
|
||||
|
||||
// find and store indices of substrings to replace
|
||||
int[] pos = new int[16];
|
||||
pos[0] = i;
|
||||
i += targLen;
|
||||
while ((j = indexOf(value, valLen, targ, targLen, i)) > 0) {
|
||||
if (++p == pos.length) {
|
||||
int cap = p + (p >> 1);
|
||||
// overflow-conscious code
|
||||
if (cap - MAX_ARRAY_SIZE > 0) {
|
||||
if (p == MAX_ARRAY_SIZE) {
|
||||
throw new OutOfMemoryError();
|
||||
}
|
||||
cap = MAX_ARRAY_SIZE;
|
||||
}
|
||||
pos = Arrays.copyOf(pos, cap);
|
||||
}
|
||||
pos[p] = j;
|
||||
i = j + targLen;
|
||||
}
|
||||
|
||||
int resultLen;
|
||||
try {
|
||||
resultLen = Math.addExact(valLen,
|
||||
Math.multiplyExact(++p, replLen - targLen));
|
||||
} catch (ArithmeticException ignored) {
|
||||
throw new OutOfMemoryError();
|
||||
}
|
||||
if (resultLen == 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
byte[] result = StringConcatHelper.newArray(resultLen);
|
||||
int posFrom = 0, posTo = 0;
|
||||
for (int q = 0; q < p; ++q) {
|
||||
int nextPos = pos[q];
|
||||
while (posFrom < nextPos) {
|
||||
result[posTo++] = value[posFrom++];
|
||||
}
|
||||
posFrom += targLen;
|
||||
for (int k = 0; k < replLen; ++k) {
|
||||
result[posTo++] = repl[k];
|
||||
}
|
||||
}
|
||||
while (posFrom < valLen) {
|
||||
result[posTo++] = value[posFrom++];
|
||||
}
|
||||
return new String(result, LATIN1);
|
||||
}
|
||||
|
||||
// case insensitive
|
||||
public static boolean regionMatchesCI(byte[] value, int toffset,
|
||||
byte[] other, int ooffset, int len) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue