< prev index next >
src/java.base/share/classes/java/lang/StringLatin1.java
Print this page
rev 54615 : [mq]: 8222955-Optimize-String-replace-CharSequence-CharSequence-for-Latin1-encoded-strings
@@ -1,7 +1,7 @@
/*
- * 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
@@ -40,10 +40,18 @@
import static java.lang.String.UTF16;
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);
}
return (char)(value[index] & 0xff);
@@ -328,10 +336,72 @@
}
}
return null; // for string to return this;
}
+ /**
+ * Precondition: targLen > 0
+ */
+ public static String replace(byte[] value, int valLen, byte[] targ,
+ int targLen, byte[] repl, int replLen)
+ {
+ int i;
+ 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 p = 0, j;
+ 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 << 1;
+ // overflow-conscious code
+ if (p >= MAX_ARRAY_SIZE - p) {
+ if (p == MAX_ARRAY_SIZE) {
+ throw new OutOfMemoryError();
+ }
+ cap = MAX_ARRAY_SIZE;
+ }
+ pos = Arrays.copyOf(pos, cap);
+ }
+ pos[p] = j;
+ i = j + targLen;
+ }
+
+ int deltaLen = replLen - targLen;
+ // overflow-conscious code
+ int resultLen = valLen + (++p) * deltaLen;
+ if (Integer.MAX_VALUE / p < deltaLen ||
+ Integer.MAX_VALUE - resultLen < 0) {
+ throw new OutOfMemoryError();
+ }
+ if (resultLen == 0) {
+ return "";
+ }
+
+ byte[] result = new byte[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) {
int last = toffset + len;
while (toffset < last) {
< prev index next >