8141132: JEP 254: Compact Strings
Adopt a more space-efficient internal representation for strings. Co-authored-by: Brent Christian <brent.christian@oracle.com> Co-authored-by: Vivek Deshpande <vivek.r.deshpande@intel.com> Co-authored-by: Charlie Hunt <charlie.hunt@oracle.com> Co-authored-by: Vladimir Kozlov <vladimir.kozlov@oracle.com> Co-authored-by: Roger Riggs <roger.riggs@oracle.com> Co-authored-by: Xueming Shen <xueming.shen@oracle.com> Co-authored-by: Aleksey Shipilev <aleksey.shipilev@oracle.com> Co-authored-by: Sandhya Viswanathan <sandhya.viswanathan@intel.com> Reviewed-by: alanb, bdelsart, coleenp, iklam, jiangli, jrose, kevinw, naoto, pliden, roland, smarks, twisti
This commit is contained in:
parent
b7dca6971d
commit
4ed5b73f3d
@ -50,12 +50,12 @@ public class $NAME_CLZ$ extends Charset
|
||||
|
||||
public CharsetDecoder newDecoder() {
|
||||
initb2c();
|
||||
return new DoubleByte.Decoder$DECTYPE$(this, b2c, b2cSB, $B2MIN$, $B2MAX$);
|
||||
return new DoubleByte.Decoder$DECTYPE$(this, b2c, b2cSB, $B2MIN$, $B2MAX$, $ASCIICOMPATIBLE$);
|
||||
}
|
||||
|
||||
public CharsetEncoder newEncoder() {
|
||||
initc2b();
|
||||
return new DoubleByte.Encoder$ENCTYPE$(this, $ENC_REPLACEMENT$ c2b, c2bIndex);
|
||||
return new DoubleByte.Encoder$ENCTYPE$(this, $ENC_REPLACEMENT$ c2b, c2bIndex, $ASCIICOMPATIBLE$);
|
||||
}
|
||||
|
||||
$B2C$
|
||||
|
@ -48,11 +48,11 @@ public class $NAME_CLZ$ extends Charset implements HistoricallyNamedCharset
|
||||
}
|
||||
|
||||
public CharsetDecoder newDecoder() {
|
||||
return new SingleByte.Decoder(this, b2c);
|
||||
return new SingleByte.Decoder(this, b2c, $ASCIICOMPATIBLE$);
|
||||
}
|
||||
|
||||
public CharsetEncoder newEncoder() {
|
||||
return new SingleByte.Encoder(this, c2b, c2bIndex);
|
||||
return new SingleByte.Encoder(this, c2b, c2bIndex, $ASCIICOMPATIBLE$);
|
||||
}
|
||||
|
||||
private final static String b2cTable = $B2CTABLE$
|
||||
|
@ -211,6 +211,7 @@ SUNWprivate_1.1 {
|
||||
Java_java_lang_SecurityManager_getClassContext;
|
||||
Java_java_lang_Shutdown_halt0;
|
||||
Java_java_lang_String_intern;
|
||||
Java_java_lang_StringUTF16_isBigEndian;
|
||||
Java_java_lang_System_identityHashCode;
|
||||
Java_java_lang_System_initProperties;
|
||||
Java_java_lang_System_mapLibraryName;
|
||||
|
@ -57,6 +57,7 @@ text: .text%Java_java_io_UnixFileSystem_list;
|
||||
text: .text%JNU_ClassString;
|
||||
text: .text%JNU_CopyObjectArray;
|
||||
text: .text%Java_java_lang_String_intern;
|
||||
text: .text%Java_java_lang_StringUTF16_isBigEndian;
|
||||
text: .text%Java_java_lang_ClassLoader_findLoadedClass0;
|
||||
text: .text%Java_java_lang_ClassLoader_findBootstrapClass;
|
||||
text: .text%Java_java_lang_Throwable_fillInStackTrace;
|
||||
|
@ -29,6 +29,7 @@ text: .text%Java_sun_reflect_Reflection_getCallerClass__;
|
||||
text: .text%Java_sun_reflect_Reflection_getCallerClass__I;
|
||||
text: .text%Java_java_lang_Class_forName0;
|
||||
text: .text%Java_java_lang_String_intern;
|
||||
text: .text%Java_java_lang_StringUTF16_isBigEndian;
|
||||
text: .text%Java_java_lang_Float_floatToRawIntBits;
|
||||
text: .text%Java_java_lang_Double_doubleToRawLongBits;
|
||||
text: .text%Java_java_lang_ClassLoader_findLoadedClass0;
|
||||
|
@ -31,6 +31,7 @@ text: .text%Java_sun_reflect_Reflection_getCallerClass__;
|
||||
text: .text%Java_sun_reflect_Reflection_getCallerClass__I;
|
||||
text: .text%Java_java_lang_Class_forName0;
|
||||
text: .text%Java_java_lang_String_intern;
|
||||
text: .text%Java_java_lang_StringUTF16_isBigEndian;
|
||||
text: .text%Java_sun_reflect_NativeConstructorAccessorImpl_newInstance0;
|
||||
text: .text%Java_java_lang_Throwable_fillInStackTrace;
|
||||
text: .text%Java_java_lang_System_setOut0;
|
||||
|
@ -197,6 +197,7 @@ public class DBCS {
|
||||
.replace("$B1MAX$" , "0x" + Integer.toString(b1Max, 16))
|
||||
.replace("$B2MIN$" , "0x" + Integer.toString(b2Min, 16))
|
||||
.replace("$B2MAX$" , "0x" + Integer.toString(b2Max, 16))
|
||||
.replace("$ASCIICOMPATIBLE$", isASCII ? "true" : "false")
|
||||
.replace("$B2C$", b2c)
|
||||
.replace("$C2BLENGTH$", "0x" + Integer.toString(c2bOff, 16))
|
||||
.replace("$NONROUNDTRIP_B2C$", b2cNR)
|
||||
|
@ -175,6 +175,9 @@ public class SBCS {
|
||||
else
|
||||
line = " return (cs instanceof " + clzName + ");";
|
||||
}
|
||||
if (line.indexOf("$ASCIICOMPATIBLE$") != -1) {
|
||||
line = line.replace("$ASCIICOMPATIBLE$", isASCII ? "true" : "false");
|
||||
}
|
||||
if (line.indexOf("$B2CTABLE$") != -1) {
|
||||
line = line.replace("$B2CTABLE$", b2c);
|
||||
}
|
||||
|
@ -31,6 +31,12 @@ import java.util.Spliterator;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import static java.lang.String.COMPACT_STRINGS;
|
||||
import static java.lang.String.UTF16;
|
||||
import static java.lang.String.LATIN1;
|
||||
import static java.lang.String.checkIndex;
|
||||
import static java.lang.String.checkOffset;
|
||||
|
||||
/**
|
||||
* A mutable sequence of characters.
|
||||
* <p>
|
||||
@ -51,7 +57,12 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
/**
|
||||
* The value is used for character storage.
|
||||
*/
|
||||
char[] value;
|
||||
byte[] value;
|
||||
|
||||
/**
|
||||
* The id of the encoding used to encode the bytes in {@code value}.
|
||||
*/
|
||||
byte coder;
|
||||
|
||||
/**
|
||||
* The count is the number of characters used.
|
||||
@ -68,7 +79,13 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
* Creates an AbstractStringBuilder of the specified capacity.
|
||||
*/
|
||||
AbstractStringBuilder(int capacity) {
|
||||
value = new char[capacity];
|
||||
if (COMPACT_STRINGS) {
|
||||
value = new byte[capacity];
|
||||
coder = LATIN1;
|
||||
} else {
|
||||
value = StringUTF16.newBytesFor(capacity);
|
||||
coder = UTF16;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -90,7 +107,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
* @return the current capacity
|
||||
*/
|
||||
public int capacity() {
|
||||
return value.length;
|
||||
return value.length >> coder;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -110,8 +127,9 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
* @param minimumCapacity the minimum desired capacity.
|
||||
*/
|
||||
public void ensureCapacity(int minimumCapacity) {
|
||||
if (minimumCapacity > 0)
|
||||
if (minimumCapacity > 0) {
|
||||
ensureCapacityInternal(minimumCapacity);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -120,24 +138,48 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
*/
|
||||
private void ensureCapacityInternal(int minimumCapacity) {
|
||||
// overflow-conscious code
|
||||
if (minimumCapacity - value.length > 0)
|
||||
int capacity = value.length >> coder;
|
||||
if (minimumCapacity - capacity > 0) {
|
||||
expandCapacity(minimumCapacity);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This implements the expansion semantics of ensureCapacity with no
|
||||
* size check or synchronization.
|
||||
*/
|
||||
void expandCapacity(int minimumCapacity) {
|
||||
int newCapacity = value.length * 2 + 2;
|
||||
if (newCapacity - minimumCapacity < 0)
|
||||
private void expandCapacity(int minimumCapacity) {
|
||||
int newCapacity = (value.length >> coder) * 2 + 2;
|
||||
if (newCapacity - minimumCapacity < 0) {
|
||||
newCapacity = minimumCapacity;
|
||||
}
|
||||
if (newCapacity < 0) {
|
||||
if (minimumCapacity < 0) // overflow
|
||||
if (minimumCapacity < 0) {// overflow
|
||||
throw new OutOfMemoryError();
|
||||
}
|
||||
newCapacity = Integer.MAX_VALUE;
|
||||
}
|
||||
value = Arrays.copyOf(value, newCapacity);
|
||||
if (coder != LATIN1 && newCapacity > StringUTF16.MAX_LENGTH) {
|
||||
if (minimumCapacity >= StringUTF16.MAX_LENGTH) {
|
||||
throw new OutOfMemoryError();
|
||||
}
|
||||
newCapacity = StringUTF16.MAX_LENGTH;
|
||||
}
|
||||
this.value = Arrays.copyOf(value, newCapacity << coder);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the coder is "isLatin1", this inflates the internal 8-bit storage
|
||||
* to 16-bit <hi=0, low> pair storage.
|
||||
*/
|
||||
private void inflate() {
|
||||
if (!isLatin1()) {
|
||||
return;
|
||||
}
|
||||
byte[] buf = StringUTF16.newBytesFor(value.length);
|
||||
StringLatin1.inflateSB(value, buf, 0, count);
|
||||
this.value = buf;
|
||||
this.coder = UTF16;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -148,8 +190,9 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
* returned by a subsequent call to the {@link #capacity()} method.
|
||||
*/
|
||||
public void trimToSize() {
|
||||
if (count < value.length) {
|
||||
value = Arrays.copyOf(value, count);
|
||||
int length = count << coder;
|
||||
if (length < value.length) {
|
||||
value = Arrays.copyOf(value, length);
|
||||
}
|
||||
}
|
||||
|
||||
@ -179,14 +222,17 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
* {@code newLength} argument is negative.
|
||||
*/
|
||||
public void setLength(int newLength) {
|
||||
if (newLength < 0)
|
||||
if (newLength < 0) {
|
||||
throw new StringIndexOutOfBoundsException(newLength);
|
||||
ensureCapacityInternal(newLength);
|
||||
|
||||
if (count < newLength) {
|
||||
Arrays.fill(value, count, newLength, '\0');
|
||||
}
|
||||
|
||||
ensureCapacityInternal(newLength);
|
||||
if (count < newLength) {
|
||||
if (isLatin1()) {
|
||||
StringLatin1.fillNull(value, count, newLength);
|
||||
} else {
|
||||
StringUTF16.fillNull(value, count, newLength);
|
||||
}
|
||||
}
|
||||
count = newLength;
|
||||
}
|
||||
|
||||
@ -209,9 +255,11 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
*/
|
||||
@Override
|
||||
public char charAt(int index) {
|
||||
if ((index < 0) || (index >= count))
|
||||
throw new StringIndexOutOfBoundsException(index);
|
||||
return value[index];
|
||||
checkIndex(index, count);
|
||||
if (isLatin1()) {
|
||||
return (char)(value[index] & 0xff);
|
||||
}
|
||||
return StringUTF16.charAt(value, index);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -236,10 +284,11 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
* sequence.
|
||||
*/
|
||||
public int codePointAt(int index) {
|
||||
if ((index < 0) || (index >= count)) {
|
||||
throw new StringIndexOutOfBoundsException(index);
|
||||
checkIndex(index, count);
|
||||
if (isLatin1()) {
|
||||
return value[index] & 0xff;
|
||||
}
|
||||
return Character.codePointAtImpl(value, index, count);
|
||||
return StringUTF16.codePointAtSB(value, index, count);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -265,10 +314,13 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
*/
|
||||
public int codePointBefore(int index) {
|
||||
int i = index - 1;
|
||||
if ((i < 0) || (i >= count)) {
|
||||
if (i < 0 || i >= count) {
|
||||
throw new StringIndexOutOfBoundsException(index);
|
||||
}
|
||||
return Character.codePointBeforeImpl(value, index, 0);
|
||||
if (isLatin1()) {
|
||||
return value[i] & 0xff;
|
||||
}
|
||||
return StringUTF16.codePointBeforeSB(value, index);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -295,7 +347,10 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
return Character.codePointCountImpl(value, beginIndex, endIndex - beginIndex);
|
||||
if (isLatin1()) {
|
||||
return endIndex - beginIndex;
|
||||
}
|
||||
return StringUTF16.codePointCountSB(value, beginIndex, endIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -321,8 +376,8 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
if (index < 0 || index > count) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
return Character.offsetByCodePointsImpl(value, 0, count,
|
||||
index, codePointOffset);
|
||||
return Character.offsetByCodePoints(this,
|
||||
index, codePointOffset);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -355,13 +410,14 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
*/
|
||||
public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
|
||||
{
|
||||
if (srcBegin < 0)
|
||||
throw new StringIndexOutOfBoundsException(srcBegin);
|
||||
if ((srcEnd < 0) || (srcEnd > count))
|
||||
throw new StringIndexOutOfBoundsException(srcEnd);
|
||||
if (srcBegin > srcEnd)
|
||||
throw new StringIndexOutOfBoundsException("srcBegin > srcEnd");
|
||||
System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
|
||||
checkRangeSIOOBE(srcBegin, srcEnd, count); // compatible to old version
|
||||
int n = srcEnd - srcBegin;
|
||||
checkRange(dstBegin, dstBegin + n, dst.length);
|
||||
if (isLatin1()) {
|
||||
StringLatin1.getCharsSB(value, srcBegin, srcEnd, dst, dstBegin);
|
||||
} else {
|
||||
StringUTF16.getCharsSB(value, srcBegin, srcEnd, dst, dstBegin);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -379,9 +435,15 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
* negative or greater than or equal to {@code length()}.
|
||||
*/
|
||||
public void setCharAt(int index, char ch) {
|
||||
if ((index < 0) || (index >= count))
|
||||
throw new StringIndexOutOfBoundsException(index);
|
||||
value[index] = ch;
|
||||
checkIndex(index, count);
|
||||
if (isLatin1() && StringLatin1.canEncode(ch)) {
|
||||
value[index] = (byte)ch;
|
||||
} else {
|
||||
if (isLatin1()) {
|
||||
inflate();
|
||||
}
|
||||
StringUTF16.putCharSB(value, index, ch);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -418,35 +480,34 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
* @return a reference to this object.
|
||||
*/
|
||||
public AbstractStringBuilder append(String str) {
|
||||
if (str == null)
|
||||
if (str == null) {
|
||||
return appendNull();
|
||||
}
|
||||
int len = str.length();
|
||||
ensureCapacityInternal(count + len);
|
||||
str.getChars(0, len, value, count);
|
||||
putStringAt(count, str);
|
||||
count += len;
|
||||
return this;
|
||||
}
|
||||
|
||||
// Documentation in subclasses because of synchro difference
|
||||
public AbstractStringBuilder append(StringBuffer sb) {
|
||||
if (sb == null)
|
||||
return appendNull();
|
||||
int len = sb.length();
|
||||
ensureCapacityInternal(count + len);
|
||||
sb.getChars(0, len, value, count);
|
||||
count += len;
|
||||
return this;
|
||||
return this.append((AbstractStringBuilder)sb);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.8
|
||||
*/
|
||||
AbstractStringBuilder append(AbstractStringBuilder asb) {
|
||||
if (asb == null)
|
||||
if (asb == null) {
|
||||
return appendNull();
|
||||
}
|
||||
int len = asb.length();
|
||||
ensureCapacityInternal(count + len);
|
||||
asb.getChars(0, len, value, count);
|
||||
if (getCoder() != asb.getCoder()) {
|
||||
inflate();
|
||||
}
|
||||
asb.getBytes(value, count, coder);
|
||||
count += len;
|
||||
return this;
|
||||
}
|
||||
@ -454,25 +515,35 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
// Documentation in subclasses because of synchro difference
|
||||
@Override
|
||||
public AbstractStringBuilder append(CharSequence s) {
|
||||
if (s == null)
|
||||
if (s == null) {
|
||||
return appendNull();
|
||||
if (s instanceof String)
|
||||
}
|
||||
if (s instanceof String) {
|
||||
return this.append((String)s);
|
||||
if (s instanceof AbstractStringBuilder)
|
||||
}
|
||||
if (s instanceof AbstractStringBuilder) {
|
||||
return this.append((AbstractStringBuilder)s);
|
||||
|
||||
}
|
||||
return this.append(s, 0, s.length());
|
||||
}
|
||||
|
||||
private AbstractStringBuilder appendNull() {
|
||||
int c = count;
|
||||
ensureCapacityInternal(c + 4);
|
||||
final char[] value = this.value;
|
||||
value[c++] = 'n';
|
||||
value[c++] = 'u';
|
||||
value[c++] = 'l';
|
||||
value[c++] = 'l';
|
||||
count = c;
|
||||
ensureCapacityInternal(count + 4);
|
||||
int count = this.count;
|
||||
byte[] val = this.value;
|
||||
if (isLatin1()) {
|
||||
val[count++] = 'n';
|
||||
val[count++] = 'u';
|
||||
val[count++] = 'l';
|
||||
val[count++] = 'l';
|
||||
} else {
|
||||
checkOffset(count + 4, val.length >> 1);
|
||||
StringUTF16.putChar(val, count++, 'n');
|
||||
StringUTF16.putChar(val, count++, 'u');
|
||||
StringUTF16.putChar(val, count++, 'l');
|
||||
StringUTF16.putChar(val, count++, 'l');
|
||||
}
|
||||
this.count = count;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -507,21 +578,13 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
*/
|
||||
@Override
|
||||
public AbstractStringBuilder append(CharSequence s, int start, int end) {
|
||||
if (s == null)
|
||||
if (s == null) {
|
||||
s = "null";
|
||||
if ((start < 0) || (start > end) || (end > s.length()))
|
||||
throw new IndexOutOfBoundsException(
|
||||
"start " + start + ", end " + end + ", s.length() "
|
||||
+ s.length());
|
||||
}
|
||||
checkRange(start, end, s.length());
|
||||
int len = end - start;
|
||||
ensureCapacityInternal(count + len);
|
||||
if (s instanceof String) {
|
||||
((String)s).getChars(start, end, value, count);
|
||||
} else {
|
||||
for (int i = start, j = count; i < end; i++, j++)
|
||||
value[j] = s.charAt(i);
|
||||
}
|
||||
count += len;
|
||||
appendChars(s, start, end);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -544,8 +607,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
public AbstractStringBuilder append(char[] str) {
|
||||
int len = str.length;
|
||||
ensureCapacityInternal(count + len);
|
||||
System.arraycopy(str, 0, value, count, len);
|
||||
count += len;
|
||||
appendChars(str, 0, len);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -572,10 +634,10 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
* or {@code offset+len > str.length}
|
||||
*/
|
||||
public AbstractStringBuilder append(char str[], int offset, int len) {
|
||||
if (len > 0) // let arraycopy report AIOOBE for len < 0
|
||||
ensureCapacityInternal(count + len);
|
||||
System.arraycopy(str, offset, value, count, len);
|
||||
count += len;
|
||||
int end = offset + len;
|
||||
checkRange(offset, end, str.length);
|
||||
ensureCapacityInternal(count + len);
|
||||
appendChars(str, offset, end);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -592,20 +654,39 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
* @return a reference to this object.
|
||||
*/
|
||||
public AbstractStringBuilder append(boolean b) {
|
||||
if (b) {
|
||||
ensureCapacityInternal(count + 4);
|
||||
value[count++] = 't';
|
||||
value[count++] = 'r';
|
||||
value[count++] = 'u';
|
||||
value[count++] = 'e';
|
||||
ensureCapacityInternal(count + (b ? 4 : 5));
|
||||
int count = this.count;
|
||||
byte[] val = this.value;
|
||||
if (isLatin1()) {
|
||||
if (b) {
|
||||
val[count++] = 't';
|
||||
val[count++] = 'r';
|
||||
val[count++] = 'u';
|
||||
val[count++] = 'e';
|
||||
} else {
|
||||
val[count++] = 'f';
|
||||
val[count++] = 'a';
|
||||
val[count++] = 'l';
|
||||
val[count++] = 's';
|
||||
val[count++] = 'e';
|
||||
}
|
||||
} else {
|
||||
ensureCapacityInternal(count + 5);
|
||||
value[count++] = 'f';
|
||||
value[count++] = 'a';
|
||||
value[count++] = 'l';
|
||||
value[count++] = 's';
|
||||
value[count++] = 'e';
|
||||
if (b) {
|
||||
checkOffset(count + 4, val.length >> 1);
|
||||
StringUTF16.putChar(val, count++, 't');
|
||||
StringUTF16.putChar(val, count++, 'r');
|
||||
StringUTF16.putChar(val, count++, 'u');
|
||||
StringUTF16.putChar(val, count++, 'e');
|
||||
} else {
|
||||
checkOffset(count + 5, val.length >> 1);
|
||||
StringUTF16.putChar(val, count++, 'f');
|
||||
StringUTF16.putChar(val, count++, 'a');
|
||||
StringUTF16.putChar(val, count++, 'l');
|
||||
StringUTF16.putChar(val, count++, 's');
|
||||
StringUTF16.putChar(val, count++, 'e');
|
||||
}
|
||||
}
|
||||
this.count = count;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -627,7 +708,14 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
@Override
|
||||
public AbstractStringBuilder append(char c) {
|
||||
ensureCapacityInternal(count + 1);
|
||||
value[count++] = c;
|
||||
if (isLatin1() && StringLatin1.canEncode(c)) {
|
||||
value[count++] = (byte)c;
|
||||
} else {
|
||||
if (isLatin1()) {
|
||||
inflate();
|
||||
}
|
||||
StringUTF16.putCharSB(value, count++, c);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -652,7 +740,13 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
: Integer.stringSize(i);
|
||||
int spaceNeeded = count + appendedLength;
|
||||
ensureCapacityInternal(spaceNeeded);
|
||||
Integer.getChars(i, spaceNeeded, value);
|
||||
if (isLatin1()) {
|
||||
Integer.getChars(i, spaceNeeded, value);
|
||||
} else {
|
||||
byte[] val = this.value;
|
||||
checkOffset(spaceNeeded, val.length >> 1);
|
||||
Integer.getCharsUTF16(i, spaceNeeded, val);
|
||||
}
|
||||
count = spaceNeeded;
|
||||
return this;
|
||||
}
|
||||
@ -678,7 +772,13 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
: Long.stringSize(l);
|
||||
int spaceNeeded = count + appendedLength;
|
||||
ensureCapacityInternal(spaceNeeded);
|
||||
Long.getChars(l, spaceNeeded, value);
|
||||
if (isLatin1()) {
|
||||
Long.getChars(l, spaceNeeded, value);
|
||||
} else {
|
||||
byte[] val = this.value;
|
||||
checkOffset(spaceNeeded, val.length >> 1);
|
||||
Long.getCharsUTF16(l, spaceNeeded, val);
|
||||
}
|
||||
count = spaceNeeded;
|
||||
return this;
|
||||
}
|
||||
@ -732,15 +832,13 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
* greater than {@code end}.
|
||||
*/
|
||||
public AbstractStringBuilder delete(int start, int end) {
|
||||
if (start < 0)
|
||||
throw new StringIndexOutOfBoundsException(start);
|
||||
if (end > count)
|
||||
if (end > count) {
|
||||
end = count;
|
||||
if (start > end)
|
||||
throw new StringIndexOutOfBoundsException();
|
||||
}
|
||||
checkRangeSIOOBE(start, end, count);
|
||||
int len = end - start;
|
||||
if (len > 0) {
|
||||
System.arraycopy(value, start+len, value, start, count-end);
|
||||
shift(end, -len);
|
||||
count -= len;
|
||||
}
|
||||
return this;
|
||||
@ -766,20 +864,10 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
* {@code codePoint} isn't a valid Unicode code point
|
||||
*/
|
||||
public AbstractStringBuilder appendCodePoint(int codePoint) {
|
||||
final int count = this.count;
|
||||
|
||||
if (Character.isBmpCodePoint(codePoint)) {
|
||||
ensureCapacityInternal(count + 1);
|
||||
value[count] = (char) codePoint;
|
||||
this.count = count + 1;
|
||||
} else if (Character.isValidCodePoint(codePoint)) {
|
||||
ensureCapacityInternal(count + 2);
|
||||
Character.toSurrogates(codePoint, value, count);
|
||||
this.count = count + 2;
|
||||
} else {
|
||||
throw new IllegalArgumentException();
|
||||
return append((char)codePoint);
|
||||
}
|
||||
return this;
|
||||
return append(Character.toChars(codePoint));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -800,9 +888,8 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
* {@code length()}.
|
||||
*/
|
||||
public AbstractStringBuilder deleteCharAt(int index) {
|
||||
if ((index < 0) || (index >= count))
|
||||
throw new StringIndexOutOfBoundsException(index);
|
||||
System.arraycopy(value, index+1, value, index, count-index-1);
|
||||
checkIndex(index, count);
|
||||
shift(index + 1, -1);
|
||||
count--;
|
||||
return this;
|
||||
}
|
||||
@ -827,22 +914,16 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
* greater than {@code end}.
|
||||
*/
|
||||
public AbstractStringBuilder replace(int start, int end, String str) {
|
||||
if (start < 0)
|
||||
throw new StringIndexOutOfBoundsException(start);
|
||||
if (start > count)
|
||||
throw new StringIndexOutOfBoundsException("start > length()");
|
||||
if (start > end)
|
||||
throw new StringIndexOutOfBoundsException("start > end");
|
||||
|
||||
if (end > count)
|
||||
if (end > count) {
|
||||
end = count;
|
||||
}
|
||||
checkRangeSIOOBE(start, end, count);
|
||||
int len = str.length();
|
||||
int newCount = count + len - (end - start);
|
||||
ensureCapacityInternal(newCount);
|
||||
|
||||
System.arraycopy(value, end, value, start + len, count - end);
|
||||
str.getChars(value, start);
|
||||
shift(end, newCount - count);
|
||||
count = newCount;
|
||||
putStringAt(start, str);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -907,13 +988,16 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
* greater than {@code end}.
|
||||
*/
|
||||
public String substring(int start, int end) {
|
||||
if (start < 0)
|
||||
throw new StringIndexOutOfBoundsException(start);
|
||||
if (end > count)
|
||||
throw new StringIndexOutOfBoundsException(end);
|
||||
if (start > end)
|
||||
throw new StringIndexOutOfBoundsException(end - start);
|
||||
return new String(value, start, end - start);
|
||||
checkRangeSIOOBE(start, end, count);
|
||||
if (isLatin1()) {
|
||||
return StringLatin1.newString(value, start, end - start);
|
||||
}
|
||||
return StringUTF16.newStringSB(value, start, end - start);
|
||||
}
|
||||
|
||||
private void shift(int offset, int n) {
|
||||
System.arraycopy(value, offset << coder,
|
||||
value, (offset + n) << coder, (count - offset) << coder);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -940,16 +1024,12 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
public AbstractStringBuilder insert(int index, char[] str, int offset,
|
||||
int len)
|
||||
{
|
||||
if ((index < 0) || (index > length()))
|
||||
throw new StringIndexOutOfBoundsException(index);
|
||||
if ((offset < 0) || (len < 0) || (offset > str.length - len))
|
||||
throw new StringIndexOutOfBoundsException(
|
||||
"offset " + offset + ", len " + len + ", str.length "
|
||||
+ str.length);
|
||||
checkOffset(index, count);
|
||||
checkRangeSIOOBE(offset, offset + len, str.length);
|
||||
ensureCapacityInternal(count + len);
|
||||
System.arraycopy(value, index, value, index + len, count - index);
|
||||
System.arraycopy(str, offset, value, index, len);
|
||||
shift(index, len);
|
||||
count += len;
|
||||
putCharsAt(index, str, offset, offset + len);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -1008,15 +1088,15 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
* @throws StringIndexOutOfBoundsException if the offset is invalid.
|
||||
*/
|
||||
public AbstractStringBuilder insert(int offset, String str) {
|
||||
if ((offset < 0) || (offset > length()))
|
||||
throw new StringIndexOutOfBoundsException(offset);
|
||||
if (str == null)
|
||||
checkOffset(offset, count);
|
||||
if (str == null) {
|
||||
str = "null";
|
||||
}
|
||||
int len = str.length();
|
||||
ensureCapacityInternal(count + len);
|
||||
System.arraycopy(value, offset, value, offset + len, count - offset);
|
||||
str.getChars(value, offset);
|
||||
shift(offset, len);
|
||||
count += len;
|
||||
putStringAt(offset, str);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -1045,13 +1125,12 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
* @throws StringIndexOutOfBoundsException if the offset is invalid.
|
||||
*/
|
||||
public AbstractStringBuilder insert(int offset, char[] str) {
|
||||
if ((offset < 0) || (offset > length()))
|
||||
throw new StringIndexOutOfBoundsException(offset);
|
||||
checkOffset(offset, count);
|
||||
int len = str.length;
|
||||
ensureCapacityInternal(count + len);
|
||||
System.arraycopy(value, offset, value, offset + len, count - offset);
|
||||
System.arraycopy(str, 0, value, offset, len);
|
||||
shift(offset, len);
|
||||
count += len;
|
||||
putCharsAt(offset, str, 0, len);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -1077,10 +1156,12 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
* @throws IndexOutOfBoundsException if the offset is invalid.
|
||||
*/
|
||||
public AbstractStringBuilder insert(int dstOffset, CharSequence s) {
|
||||
if (s == null)
|
||||
if (s == null) {
|
||||
s = "null";
|
||||
if (s instanceof String)
|
||||
}
|
||||
if (s instanceof String) {
|
||||
return this.insert(dstOffset, (String)s);
|
||||
}
|
||||
return this.insert(dstOffset, s, 0, s.length());
|
||||
}
|
||||
|
||||
@ -1128,23 +1209,19 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
* {@code start} is greater than {@code end} or
|
||||
* {@code end} is greater than {@code s.length()}
|
||||
*/
|
||||
public AbstractStringBuilder insert(int dstOffset, CharSequence s,
|
||||
int start, int end) {
|
||||
if (s == null)
|
||||
public AbstractStringBuilder insert(int dstOffset, CharSequence s,
|
||||
int start, int end)
|
||||
{
|
||||
if (s == null) {
|
||||
s = "null";
|
||||
if ((dstOffset < 0) || (dstOffset > this.length()))
|
||||
throw new IndexOutOfBoundsException("dstOffset "+dstOffset);
|
||||
if ((start < 0) || (end < 0) || (start > end) || (end > s.length()))
|
||||
throw new IndexOutOfBoundsException(
|
||||
"start " + start + ", end " + end + ", s.length() "
|
||||
+ s.length());
|
||||
}
|
||||
checkOffset(dstOffset, count);
|
||||
checkRange(start, end, s.length());
|
||||
int len = end - start;
|
||||
ensureCapacityInternal(count + len);
|
||||
System.arraycopy(value, dstOffset, value, dstOffset + len,
|
||||
count - dstOffset);
|
||||
for (int i=start; i<end; i++)
|
||||
value[dstOffset++] = s.charAt(i);
|
||||
shift(dstOffset, len);
|
||||
count += len;
|
||||
putCharsAt(dstOffset, s, start, end);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -1191,10 +1268,18 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
* @throws IndexOutOfBoundsException if the offset is invalid.
|
||||
*/
|
||||
public AbstractStringBuilder insert(int offset, char c) {
|
||||
checkOffset(offset, count);
|
||||
ensureCapacityInternal(count + 1);
|
||||
System.arraycopy(value, offset, value, offset + 1, count - offset);
|
||||
value[offset] = c;
|
||||
shift(offset, 1);
|
||||
count += 1;
|
||||
if (isLatin1() && StringLatin1.canEncode(c)) {
|
||||
value[offset] = (byte)c;
|
||||
} else {
|
||||
if (isLatin1()) {
|
||||
inflate();
|
||||
}
|
||||
StringUTF16.putCharSB(value, offset, c);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -1326,7 +1411,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
* or {@code -1} if there is no such occurrence.
|
||||
*/
|
||||
public int indexOf(String str, int fromIndex) {
|
||||
return String.indexOf(value, 0, count, str, fromIndex);
|
||||
return String.indexOf(value, coder, count, str, fromIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1366,7 +1451,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
* or {@code -1} if there is no such occurrence.
|
||||
*/
|
||||
public int lastIndexOf(String str, int fromIndex) {
|
||||
return String.lastIndexOf(value, 0, count, str, fromIndex);
|
||||
return String.lastIndexOf(value, coder, count, str, fromIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1392,34 +1477,47 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
* @return a reference to this object.
|
||||
*/
|
||||
public AbstractStringBuilder reverse() {
|
||||
boolean hasSurrogates = false;
|
||||
byte[] val = this.value;
|
||||
int count = this.count;
|
||||
int coder = this.coder;
|
||||
int n = count - 1;
|
||||
for (int j = (n-1) >> 1; j >= 0; j--) {
|
||||
int k = n - j;
|
||||
char cj = value[j];
|
||||
char ck = value[k];
|
||||
value[j] = ck;
|
||||
value[k] = cj;
|
||||
if (Character.isSurrogate(cj) ||
|
||||
Character.isSurrogate(ck)) {
|
||||
hasSurrogates = true;
|
||||
if (COMPACT_STRINGS && coder == LATIN1) {
|
||||
for (int j = (n-1) >> 1; j >= 0; j--) {
|
||||
int k = n - j;
|
||||
byte cj = val[j];
|
||||
val[j] = val[k];
|
||||
val[k] = cj;
|
||||
}
|
||||
} else {
|
||||
checkOffset(count, val.length >> 1);
|
||||
boolean hasSurrogates = false;
|
||||
for (int j = (n-1) >> 1; j >= 0; j--) {
|
||||
int k = n - j;
|
||||
char cj = StringUTF16.getChar(val, j);
|
||||
char ck = StringUTF16.getChar(val, k);
|
||||
StringUTF16.putChar(val, j, ck);
|
||||
StringUTF16.putChar(val, k, cj);
|
||||
if (Character.isSurrogate(cj) ||
|
||||
Character.isSurrogate(ck)) {
|
||||
hasSurrogates = true;
|
||||
}
|
||||
}
|
||||
if (hasSurrogates) {
|
||||
reverseAllValidSurrogatePairs(val, count);
|
||||
}
|
||||
}
|
||||
if (hasSurrogates) {
|
||||
reverseAllValidSurrogatePairs();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Outlined helper method for reverse() */
|
||||
private void reverseAllValidSurrogatePairs() {
|
||||
private void reverseAllValidSurrogatePairs(byte[] val, int count) {
|
||||
for (int i = 0; i < count - 1; i++) {
|
||||
char c2 = value[i];
|
||||
char c2 = StringUTF16.getChar(val, i);
|
||||
if (Character.isLowSurrogate(c2)) {
|
||||
char c1 = value[i + 1];
|
||||
char c1 = StringUTF16.getChar(val, i + 1);
|
||||
if (Character.isHighSurrogate(c1)) {
|
||||
value[i++] = c1;
|
||||
value[i] = c2;
|
||||
StringUTF16.putChar(val, i++, c1);
|
||||
StringUTF16.putChar(val, i, c2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1444,10 +1542,13 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
*/
|
||||
@Override
|
||||
public IntStream chars() {
|
||||
byte[] val = this.value; int count = this.count; byte coder = this.coder;
|
||||
checkOffset(count, val.length >> coder);
|
||||
// Reuse String-based spliterator. This requires a supplier to
|
||||
// capture the value and count when the terminal operation is executed
|
||||
return StreamSupport.intStream(
|
||||
() -> new String.IntCharArraySpliterator(value, 0, count, 0),
|
||||
() -> coder == LATIN1 ? new StringLatin1.CharsSpliterator(val, 0, count, 0)
|
||||
: new StringUTF16.CharsSpliterator(val, 0, count, 0),
|
||||
Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED,
|
||||
false);
|
||||
}
|
||||
@ -1458,10 +1559,13 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
*/
|
||||
@Override
|
||||
public IntStream codePoints() {
|
||||
byte[] val = this.value; int count = this.count; byte coder = this.coder;
|
||||
checkOffset(count, val.length >> coder);
|
||||
// Reuse String-based spliterator. This requires a supplier to
|
||||
// capture the value and count when the terminal operation is executed
|
||||
return StreamSupport.intStream(
|
||||
() -> new String.CodePointsSpliterator(value, 0, count, 0),
|
||||
() -> coder == LATIN1 ? new StringLatin1.CharsSpliterator(val, 0, count, 0)
|
||||
: new StringUTF16.CodePointsSpliterator(val, 0, count, 0),
|
||||
Spliterator.ORDERED,
|
||||
false);
|
||||
}
|
||||
@ -1469,8 +1573,147 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
/**
|
||||
* Needed by {@code String} for the contentEquals method.
|
||||
*/
|
||||
final char[] getValue() {
|
||||
final byte[] getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
* Invoker guarantees it is in UTF16 (inflate itself for asb), if two
|
||||
* coders are different and the dstBegin has enough space
|
||||
*
|
||||
* @param dstBegin the char index, not offset of byte[]
|
||||
* @param coder the coder of dst[]
|
||||
*/
|
||||
protected void getBytes(byte dst[], int dstBegin, byte coder) {
|
||||
if (this.coder == coder) {
|
||||
System.arraycopy(value, 0, dst, dstBegin << coder, count << coder);
|
||||
} else { // this.coder == LATIN && coder == UTF16
|
||||
StringLatin1.inflateSB(value, dst, dstBegin, count);
|
||||
}
|
||||
}
|
||||
|
||||
/* for readObject() */
|
||||
protected void initBytes(char[] value, int off, int len) {
|
||||
if (String.COMPACT_STRINGS) {
|
||||
this.value = StringUTF16.compress(value, off, len);
|
||||
if (this.value != null) {
|
||||
this.coder = LATIN1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.coder = UTF16;
|
||||
this.value = StringUTF16.toBytes(value, off, len);
|
||||
}
|
||||
|
||||
final byte getCoder() {
|
||||
return COMPACT_STRINGS ? coder : UTF16;
|
||||
}
|
||||
|
||||
final boolean isLatin1() {
|
||||
return COMPACT_STRINGS && coder == LATIN1;
|
||||
}
|
||||
|
||||
private final void putCharsAt(int index, char[] s, int off, int end) {
|
||||
if (isLatin1()) {
|
||||
byte[] val = this.value;
|
||||
for (int i = off, j = index; i < end; i++) {
|
||||
char c = s[i];
|
||||
if (StringLatin1.canEncode(c)) {
|
||||
val[j++] = (byte)c;
|
||||
} else {
|
||||
inflate();
|
||||
StringUTF16.putCharsSB(this.value, j, s, i, end);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
StringUTF16.putCharsSB(this.value, index, s, off, end);
|
||||
}
|
||||
}
|
||||
|
||||
private final void putCharsAt(int index, CharSequence s, int off, int end) {
|
||||
if (isLatin1()) {
|
||||
byte[] val = this.value;
|
||||
for (int i = off, j = index; i < end; i++) {
|
||||
char c = s.charAt(i);
|
||||
if (StringLatin1.canEncode(c)) {
|
||||
val[j++] = (byte)c;
|
||||
} else {
|
||||
inflate();
|
||||
StringUTF16.putCharsSB(this.value, j, s, i, end);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
StringUTF16.putCharsSB(this.value, index, s, off, end);
|
||||
}
|
||||
}
|
||||
|
||||
private final void putStringAt(int index, String str) {
|
||||
if (getCoder() != str.coder()) {
|
||||
inflate();
|
||||
}
|
||||
byte[] val = this.value;
|
||||
byte coder = this.coder;
|
||||
checkOffset(index + str.length(), val.length >> coder);
|
||||
str.getBytes(val, index, coder);
|
||||
}
|
||||
|
||||
private final void appendChars(char[] s, int off, int end) {
|
||||
if (isLatin1()) {
|
||||
byte[] val = this.value;
|
||||
for (int i = off, j = count; i < end; i++) {
|
||||
char c = s[i];
|
||||
if (StringLatin1.canEncode(c)) {
|
||||
val[j++] = (byte)c;
|
||||
} else {
|
||||
count = j;
|
||||
inflate();
|
||||
StringUTF16.putCharsSB(this.value, j, s, i, end);
|
||||
count += end - i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
StringUTF16.putCharsSB(this.value, count, s, off, end);
|
||||
}
|
||||
count += end - off;
|
||||
}
|
||||
|
||||
private final void appendChars(CharSequence s, int off, int end) {
|
||||
if (isLatin1()) {
|
||||
byte[] val = this.value;
|
||||
for (int i = off, j = count; i < end; i++) {
|
||||
char c = s.charAt(i);
|
||||
if (StringLatin1.canEncode(c)) {
|
||||
val[j++] = (byte)c;
|
||||
} else {
|
||||
count = j;
|
||||
inflate();
|
||||
StringUTF16.putCharsSB(this.value, j, s, i, end);
|
||||
count += end - i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
StringUTF16.putCharsSB(this.value, count, s, off, end);
|
||||
}
|
||||
count += end - off;
|
||||
}
|
||||
|
||||
/* IndexOutOfBoundsException, if out of bounds */
|
||||
private static void checkRange(int start, int end, int len) {
|
||||
if (start < 0 || start > end || end > len) {
|
||||
throw new IndexOutOfBoundsException(
|
||||
"start " + start + ", end " + end + ", length " + len);
|
||||
}
|
||||
}
|
||||
|
||||
/* StringIndexOutOfBoundsException, if out of bounds */
|
||||
private static void checkRangeSIOOBE(int start, int end, int len) {
|
||||
if (start < 0 || start > end || end > len) {
|
||||
throw new StringIndexOutOfBoundsException(
|
||||
"start " + start + ", end " + end + ", length " + len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,10 @@ import java.lang.annotation.Native;
|
||||
import java.util.Objects;
|
||||
import jdk.internal.HotSpotIntrinsicCandidate;
|
||||
|
||||
import static java.lang.String.COMPACT_STRINGS;
|
||||
import static java.lang.String.LATIN1;
|
||||
import static java.lang.String.UTF16;
|
||||
|
||||
/**
|
||||
* The {@code Integer} class wraps a value of the primitive type
|
||||
* {@code int} in an object. An object of type {@code Integer}
|
||||
@ -138,25 +142,47 @@ public final class Integer extends Number implements Comparable<Integer> {
|
||||
return toString(i);
|
||||
}
|
||||
|
||||
char buf[] = new char[33];
|
||||
if (COMPACT_STRINGS) {
|
||||
byte[] buf = new byte[33];
|
||||
boolean negative = (i < 0);
|
||||
int charPos = 32;
|
||||
|
||||
if (!negative) {
|
||||
i = -i;
|
||||
}
|
||||
|
||||
while (i <= -radix) {
|
||||
buf[charPos--] = (byte)digits[-(i % radix)];
|
||||
i = i / radix;
|
||||
}
|
||||
buf[charPos] = (byte)digits[-i];
|
||||
|
||||
if (negative) {
|
||||
buf[--charPos] = '-';
|
||||
}
|
||||
|
||||
return StringLatin1.newString(buf, charPos, (33 - charPos));
|
||||
}
|
||||
return toStringUTF16(i, radix);
|
||||
}
|
||||
|
||||
private static String toStringUTF16(int i, int radix) {
|
||||
byte[] buf = new byte[33 * 2];
|
||||
boolean negative = (i < 0);
|
||||
int charPos = 32;
|
||||
|
||||
if (!negative) {
|
||||
i = -i;
|
||||
}
|
||||
|
||||
while (i <= -radix) {
|
||||
buf[charPos--] = digits[-(i % radix)];
|
||||
StringUTF16.putChar(buf, charPos--, digits[-(i % radix)]);
|
||||
i = i / radix;
|
||||
}
|
||||
buf[charPos] = digits[-i];
|
||||
StringUTF16.putChar(buf, charPos, digits[-i]);
|
||||
|
||||
if (negative) {
|
||||
buf[--charPos] = '-';
|
||||
StringUTF16.putChar(buf, --charPos, '-');
|
||||
}
|
||||
|
||||
return new String(buf, charPos, (33 - charPos));
|
||||
return StringUTF16.newString(buf, charPos, (33 - charPos));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -312,12 +338,16 @@ public final class Integer extends Number implements Comparable<Integer> {
|
||||
// assert shift > 0 && shift <=5 : "Illegal shift value";
|
||||
int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val);
|
||||
int chars = Math.max(((mag + (shift - 1)) / shift), 1);
|
||||
char[] buf = new char[chars];
|
||||
|
||||
formatUnsignedInt(val, shift, buf, 0, chars);
|
||||
|
||||
// Use special constructor which takes over "buf".
|
||||
return new String(buf, true);
|
||||
if (COMPACT_STRINGS) {
|
||||
byte[] buf = new byte[chars];
|
||||
formatUnsignedInt(val, shift, buf, 0, chars);
|
||||
return new String(buf, LATIN1);
|
||||
} else {
|
||||
byte[] buf = new byte[chars * 2];
|
||||
formatUnsignedIntUTF16(val, shift, buf, 0, chars);
|
||||
return new String(buf, UTF16);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -331,7 +361,7 @@ public final class Integer extends Number implements Comparable<Integer> {
|
||||
* @param offset the offset in the destination buffer to start at
|
||||
* @param len the number of characters to write
|
||||
*/
|
||||
static void formatUnsignedInt(int val, int shift, char[] buf, int offset, int len) {
|
||||
static void formatUnsignedInt(int val, int shift, char[] buf, int offset, int len) {
|
||||
// assert shift > 0 && shift <=5 : "Illegal shift value";
|
||||
// assert offset >= 0 && offset < buf.length : "illegal offset";
|
||||
// assert len > 0 && (offset + len) <= buf.length : "illegal length";
|
||||
@ -344,6 +374,28 @@ public final class Integer extends Number implements Comparable<Integer> {
|
||||
} while (charPos > offset);
|
||||
}
|
||||
|
||||
/** byte[]/LATIN1 version */
|
||||
static void formatUnsignedInt(int val, int shift, byte[] buf, int offset, int len) {
|
||||
int charPos = offset + len;
|
||||
int radix = 1 << shift;
|
||||
int mask = radix - 1;
|
||||
do {
|
||||
buf[--charPos] = (byte)Integer.digits[val & mask];
|
||||
val >>>= shift;
|
||||
} while (charPos > offset);
|
||||
}
|
||||
|
||||
/** byte[]/UTF16 version */
|
||||
static void formatUnsignedIntUTF16(int val, int shift, byte[] buf, int offset, int len) {
|
||||
int charPos = offset + len;
|
||||
int radix = 1 << shift;
|
||||
int mask = radix - 1;
|
||||
do {
|
||||
StringUTF16.putChar(buf, --charPos, Integer.digits[val & mask]);
|
||||
val >>>= shift;
|
||||
} while (charPos > offset);
|
||||
}
|
||||
|
||||
static final char [] DigitTens = {
|
||||
'0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
|
||||
'1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
|
||||
@ -401,9 +453,15 @@ public final class Integer extends Number implements Comparable<Integer> {
|
||||
if (i == Integer.MIN_VALUE)
|
||||
return "-2147483648";
|
||||
int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
|
||||
char[] buf = new char[size];
|
||||
getChars(i, size, buf);
|
||||
return new String(buf, true);
|
||||
if (COMPACT_STRINGS) {
|
||||
byte[] buf = new byte[size];
|
||||
getChars(i, size, buf);
|
||||
return new String(buf, LATIN1);
|
||||
} else {
|
||||
byte[] buf = new byte[size * 2];
|
||||
getCharsUTF16(i, size, buf);
|
||||
return new String(buf, UTF16);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -433,7 +491,7 @@ public final class Integer extends Number implements Comparable<Integer> {
|
||||
*
|
||||
* Will fail if i == Integer.MIN_VALUE
|
||||
*/
|
||||
static void getChars(int i, int index, char[] buf) {
|
||||
static void getChars(int i, int index, byte[] buf) {
|
||||
int q, r;
|
||||
int charPos = index;
|
||||
char sign = 0;
|
||||
@ -449,8 +507,8 @@ public final class Integer extends Number implements Comparable<Integer> {
|
||||
// really: r = i - (q * 100);
|
||||
r = i - ((q << 6) + (q << 5) + (q << 2));
|
||||
i = q;
|
||||
buf [--charPos] = DigitOnes[r];
|
||||
buf [--charPos] = DigitTens[r];
|
||||
buf [--charPos] = (byte)DigitOnes[r];
|
||||
buf [--charPos] = (byte)DigitTens[r];
|
||||
}
|
||||
|
||||
// Fall thru to fast mode for smaller numbers
|
||||
@ -458,12 +516,46 @@ public final class Integer extends Number implements Comparable<Integer> {
|
||||
for (;;) {
|
||||
q = (i * 52429) >>> (16+3);
|
||||
r = i - ((q << 3) + (q << 1)); // r = i-(q*10) ...
|
||||
buf [--charPos] = digits [r];
|
||||
buf [--charPos] = (byte)digits [r];
|
||||
i = q;
|
||||
if (i == 0) break;
|
||||
}
|
||||
if (sign != 0) {
|
||||
buf [--charPos] = sign;
|
||||
buf [--charPos] = (byte)sign;
|
||||
}
|
||||
}
|
||||
|
||||
static void getCharsUTF16(int i, int index, byte[] buf) {
|
||||
int q, r;
|
||||
int charPos = index;
|
||||
char sign = 0;
|
||||
|
||||
if (i < 0) {
|
||||
sign = '-';
|
||||
i = -i;
|
||||
}
|
||||
|
||||
// Generate two digits per iteration
|
||||
while (i >= 65536) {
|
||||
q = i / 100;
|
||||
// really: r = i - (q * 100);
|
||||
r = i - ((q << 6) + (q << 5) + (q << 2));
|
||||
i = q;
|
||||
StringUTF16.putChar(buf, --charPos, DigitOnes[r]);
|
||||
StringUTF16.putChar(buf, --charPos, DigitTens[r]);
|
||||
}
|
||||
|
||||
// Fall thru to fast mode for smaller numbers
|
||||
// assert(i <= 65536, i);
|
||||
for (;;) {
|
||||
q = (i * 52429) >>> (16+3);
|
||||
r = i - ((q << 3) + (q << 1)); // r = i-(q*10) ...
|
||||
StringUTF16.putChar(buf, --charPos, Integer.digits[r]);
|
||||
i = q;
|
||||
if (i == 0) break;
|
||||
}
|
||||
if (sign != 0) {
|
||||
StringUTF16.putChar(buf, --charPos, sign);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,9 @@ import java.math.*;
|
||||
import java.util.Objects;
|
||||
import jdk.internal.HotSpotIntrinsicCandidate;
|
||||
|
||||
import static java.lang.String.COMPACT_STRINGS;
|
||||
import static java.lang.String.LATIN1;
|
||||
import static java.lang.String.UTF16;
|
||||
|
||||
/**
|
||||
* The {@code Long} class wraps a value of the primitive type {@code
|
||||
@ -124,25 +127,46 @@ public final class Long extends Number implements Comparable<Long> {
|
||||
radix = 10;
|
||||
if (radix == 10)
|
||||
return toString(i);
|
||||
char[] buf = new char[65];
|
||||
|
||||
if (COMPACT_STRINGS) {
|
||||
byte[] buf = new byte[65];
|
||||
int charPos = 64;
|
||||
boolean negative = (i < 0);
|
||||
|
||||
if (!negative) {
|
||||
i = -i;
|
||||
}
|
||||
|
||||
while (i <= -radix) {
|
||||
buf[charPos--] = (byte)Integer.digits[(int)(-(i % radix))];
|
||||
i = i / radix;
|
||||
}
|
||||
buf[charPos] = (byte)Integer.digits[(int)(-i)];
|
||||
|
||||
if (negative) {
|
||||
buf[--charPos] = '-';
|
||||
}
|
||||
return StringLatin1.newString(buf, charPos, (65 - charPos));
|
||||
}
|
||||
return toStringUTF16(i, radix);
|
||||
}
|
||||
|
||||
private static String toStringUTF16(long i, int radix) {
|
||||
byte[] buf = new byte[65 * 2];
|
||||
int charPos = 64;
|
||||
boolean negative = (i < 0);
|
||||
|
||||
if (!negative) {
|
||||
i = -i;
|
||||
}
|
||||
|
||||
while (i <= -radix) {
|
||||
buf[charPos--] = Integer.digits[(int)(-(i % radix))];
|
||||
StringUTF16.putChar(buf, charPos--, Integer.digits[(int)(-(i % radix))]);
|
||||
i = i / radix;
|
||||
}
|
||||
buf[charPos] = Integer.digits[(int)(-i)];
|
||||
|
||||
StringUTF16.putChar(buf, charPos, Integer.digits[(int)(-i)]);
|
||||
if (negative) {
|
||||
buf[--charPos] = '-';
|
||||
StringUTF16.putChar(buf, --charPos, '-');
|
||||
}
|
||||
|
||||
return new String(buf, charPos, (65 - charPos));
|
||||
return StringUTF16.newString(buf, charPos, (65 - charPos));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -355,10 +379,16 @@ public final class Long extends Number implements Comparable<Long> {
|
||||
// assert shift > 0 && shift <=5 : "Illegal shift value";
|
||||
int mag = Long.SIZE - Long.numberOfLeadingZeros(val);
|
||||
int chars = Math.max(((mag + (shift - 1)) / shift), 1);
|
||||
char[] buf = new char[chars];
|
||||
|
||||
formatUnsignedLong(val, shift, buf, 0, chars);
|
||||
return new String(buf, true);
|
||||
if (COMPACT_STRINGS) {
|
||||
byte[] buf = new byte[chars];
|
||||
formatUnsignedLong0(val, shift, buf, 0, chars);
|
||||
return new String(buf, LATIN1);
|
||||
} else {
|
||||
byte[] buf = new byte[chars * 2];
|
||||
formatUnsignedLong0UTF16(val, shift, buf, 0, chars);
|
||||
return new String(buf, UTF16);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -385,6 +415,28 @@ public final class Long extends Number implements Comparable<Long> {
|
||||
} while (charPos > offset);
|
||||
}
|
||||
|
||||
/** byte[]/LATIN1 version */
|
||||
static void formatUnsignedLong0(long val, int shift, byte[] buf, int offset, int len) {
|
||||
int charPos = offset + len;
|
||||
int radix = 1 << shift;
|
||||
int mask = radix - 1;
|
||||
do {
|
||||
buf[--charPos] = (byte)Integer.digits[((int) val) & mask];
|
||||
val >>>= shift;
|
||||
} while (charPos > offset);
|
||||
}
|
||||
|
||||
/** byte[]/UTF16 version */
|
||||
static void formatUnsignedLong0UTF16(long val, int shift, byte[] buf, int offset, int len) {
|
||||
int charPos = offset + len;
|
||||
int radix = 1 << shift;
|
||||
int mask = radix - 1;
|
||||
do {
|
||||
StringUTF16.putChar(buf, --charPos, Integer.digits[((int) val) & mask]);
|
||||
val >>>= shift;
|
||||
} while (charPos > offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@code String} object representing the specified
|
||||
* {@code long}. The argument is converted to signed decimal
|
||||
@ -399,9 +451,15 @@ public final class Long extends Number implements Comparable<Long> {
|
||||
if (i == Long.MIN_VALUE)
|
||||
return "-9223372036854775808";
|
||||
int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
|
||||
char[] buf = new char[size];
|
||||
getChars(i, size, buf);
|
||||
return new String(buf, true);
|
||||
if (COMPACT_STRINGS) {
|
||||
byte[] buf = new byte[size];
|
||||
getChars(i, size, buf);
|
||||
return new String(buf, LATIN1);
|
||||
} else {
|
||||
byte[] buf = new byte[size * 2];
|
||||
getCharsUTF16(i, size, buf);
|
||||
return new String(buf, UTF16);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -431,7 +489,7 @@ public final class Long extends Number implements Comparable<Long> {
|
||||
*
|
||||
* Will fail if i == Long.MIN_VALUE
|
||||
*/
|
||||
static void getChars(long i, int index, char[] buf) {
|
||||
static void getChars(long i, int index, byte[] buf) {
|
||||
long q;
|
||||
int r;
|
||||
int charPos = index;
|
||||
@ -448,8 +506,8 @@ public final class Long extends Number implements Comparable<Long> {
|
||||
// really: r = i - (q * 100);
|
||||
r = (int)(i - ((q << 6) + (q << 5) + (q << 2)));
|
||||
i = q;
|
||||
buf[--charPos] = Integer.DigitOnes[r];
|
||||
buf[--charPos] = Integer.DigitTens[r];
|
||||
buf[--charPos] = (byte)Integer.DigitOnes[r];
|
||||
buf[--charPos] = (byte)Integer.DigitTens[r];
|
||||
}
|
||||
|
||||
// Get 2 digits/iteration using ints
|
||||
@ -460,8 +518,8 @@ public final class Long extends Number implements Comparable<Long> {
|
||||
// really: r = i2 - (q * 100);
|
||||
r = i2 - ((q2 << 6) + (q2 << 5) + (q2 << 2));
|
||||
i2 = q2;
|
||||
buf[--charPos] = Integer.DigitOnes[r];
|
||||
buf[--charPos] = Integer.DigitTens[r];
|
||||
buf[--charPos] = (byte)Integer.DigitOnes[r];
|
||||
buf[--charPos] = (byte)Integer.DigitTens[r];
|
||||
}
|
||||
|
||||
// Fall thru to fast mode for smaller numbers
|
||||
@ -469,12 +527,59 @@ public final class Long extends Number implements Comparable<Long> {
|
||||
for (;;) {
|
||||
q2 = (i2 * 52429) >>> (16+3);
|
||||
r = i2 - ((q2 << 3) + (q2 << 1)); // r = i2-(q2*10) ...
|
||||
buf[--charPos] = Integer.digits[r];
|
||||
buf[--charPos] = (byte)Integer.digits[r];
|
||||
i2 = q2;
|
||||
if (i2 == 0) break;
|
||||
}
|
||||
if (sign != 0) {
|
||||
buf[--charPos] = sign;
|
||||
buf[--charPos] = (byte)sign;
|
||||
}
|
||||
}
|
||||
|
||||
static void getCharsUTF16(long i, int index, byte[] buf) {
|
||||
long q;
|
||||
int r;
|
||||
int charPos = index;
|
||||
char sign = 0;
|
||||
|
||||
if (i < 0) {
|
||||
sign = '-';
|
||||
i = -i;
|
||||
}
|
||||
|
||||
// Get 2 digits/iteration using longs until quotient fits into an int
|
||||
while (i > Integer.MAX_VALUE) {
|
||||
q = i / 100;
|
||||
// really: r = i - (q * 100);
|
||||
r = (int)(i - ((q << 6) + (q << 5) + (q << 2)));
|
||||
i = q;
|
||||
StringUTF16.putChar(buf, --charPos, Integer.DigitOnes[r]);
|
||||
StringUTF16.putChar(buf, --charPos, Integer.DigitTens[r]);
|
||||
}
|
||||
|
||||
// Get 2 digits/iteration using ints
|
||||
int q2;
|
||||
int i2 = (int)i;
|
||||
while (i2 >= 65536) {
|
||||
q2 = i2 / 100;
|
||||
// really: r = i2 - (q * 100);
|
||||
r = i2 - ((q2 << 6) + (q2 << 5) + (q2 << 2));
|
||||
i2 = q2;
|
||||
StringUTF16.putChar(buf, --charPos, Integer.DigitOnes[r]);
|
||||
StringUTF16.putChar(buf, --charPos, Integer.DigitTens[r]);
|
||||
}
|
||||
|
||||
// Fall thru to fast mode for smaller numbers
|
||||
// assert(i2 <= 65536, i2);
|
||||
for (;;) {
|
||||
q2 = (i2 * 52429) >>> (16+3);
|
||||
r = i2 - ((q2 << 3) + (q2 << 1)); // r = i2-(q2*10) ...
|
||||
StringUTF16.putChar(buf, --charPos, Integer.digits[r]);
|
||||
i2 = q2;
|
||||
if (i2 == 0) break;
|
||||
}
|
||||
if (sign != 0) {
|
||||
StringUTF16.putChar(buf, --charPos, sign);
|
||||
}
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -104,7 +104,7 @@ import jdk.internal.HotSpotIntrinsicCandidate;
|
||||
* A cache of the last value returned by toString. Cleared
|
||||
* whenever the StringBuffer is modified.
|
||||
*/
|
||||
private transient char[] toStringCache;
|
||||
private transient String toStringCache;
|
||||
|
||||
/** use serialVersionUID from JDK 1.0.2 for interoperability */
|
||||
static final long serialVersionUID = 3388685877147921107L;
|
||||
@ -169,15 +169,13 @@ import jdk.internal.HotSpotIntrinsicCandidate;
|
||||
|
||||
@Override
|
||||
public synchronized int capacity() {
|
||||
return value.length;
|
||||
return super.capacity();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public synchronized void ensureCapacity(int minimumCapacity) {
|
||||
if (minimumCapacity > value.length) {
|
||||
expandCapacity(minimumCapacity);
|
||||
}
|
||||
super.ensureCapacity(minimumCapacity);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -204,9 +202,7 @@ import jdk.internal.HotSpotIntrinsicCandidate;
|
||||
*/
|
||||
@Override
|
||||
public synchronized char charAt(int index) {
|
||||
if ((index < 0) || (index >= count))
|
||||
throw new StringIndexOutOfBoundsException(index);
|
||||
return value[index];
|
||||
return super.charAt(index);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -261,10 +257,8 @@ import jdk.internal.HotSpotIntrinsicCandidate;
|
||||
*/
|
||||
@Override
|
||||
public synchronized void setCharAt(int index, char ch) {
|
||||
if ((index < 0) || (index >= count))
|
||||
throw new StringIndexOutOfBoundsException(index);
|
||||
toStringCache = null;
|
||||
value[index] = ch;
|
||||
super.setCharAt(index, ch);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -680,9 +674,11 @@ import jdk.internal.HotSpotIntrinsicCandidate;
|
||||
@HotSpotIntrinsicCandidate
|
||||
public synchronized String toString() {
|
||||
if (toStringCache == null) {
|
||||
toStringCache = Arrays.copyOfRange(value, 0, count);
|
||||
return toStringCache =
|
||||
isLatin1() ? StringLatin1.newString(value, 0, count)
|
||||
: StringUTF16.newString(value, 0, count);
|
||||
}
|
||||
return new String(toStringCache, true);
|
||||
return new String(toStringCache);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -710,7 +706,13 @@ import jdk.internal.HotSpotIntrinsicCandidate;
|
||||
private synchronized void writeObject(java.io.ObjectOutputStream s)
|
||||
throws java.io.IOException {
|
||||
java.io.ObjectOutputStream.PutField fields = s.putFields();
|
||||
fields.put("value", value);
|
||||
char[] val = new char[capacity()];
|
||||
if (isLatin1()) {
|
||||
StringLatin1.getChars(value, 0, count, val, 0);
|
||||
} else {
|
||||
StringUTF16.getChars(value, 0, count, val, 0);
|
||||
}
|
||||
fields.put("value", val);
|
||||
fields.put("count", count);
|
||||
fields.put("shared", false);
|
||||
s.writeFields();
|
||||
@ -723,7 +725,12 @@ import jdk.internal.HotSpotIntrinsicCandidate;
|
||||
private void readObject(java.io.ObjectInputStream s)
|
||||
throws java.io.IOException, ClassNotFoundException {
|
||||
java.io.ObjectInputStream.GetField fields = s.readFields();
|
||||
value = (char[])fields.get("value", null);
|
||||
char[] val = (char[])fields.get("value", null);
|
||||
initBytes(val, 0, val.length);
|
||||
count = fields.get("count", 0);
|
||||
}
|
||||
|
||||
protected synchronized void getBytes(byte dst[], int dstBegin, byte coder) {
|
||||
super.getBytes(dst, dstBegin, coder);
|
||||
}
|
||||
}
|
||||
|
@ -412,7 +412,8 @@ public final class StringBuilder
|
||||
@HotSpotIntrinsicCandidate
|
||||
public String toString() {
|
||||
// Create a copy, don't share the array
|
||||
return new String(value, 0, count);
|
||||
return isLatin1() ? StringLatin1.newString(value, 0, count)
|
||||
: StringUTF16.newStringSB(value, 0, count);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -430,7 +431,13 @@ public final class StringBuilder
|
||||
throws java.io.IOException {
|
||||
s.defaultWriteObject();
|
||||
s.writeInt(count);
|
||||
s.writeObject(value);
|
||||
char[] val = new char[capacity()];
|
||||
if (isLatin1()) {
|
||||
StringLatin1.getChars(value, 0, count, val, 0);
|
||||
} else {
|
||||
StringUTF16.getChars(value, 0, count, val, 0);
|
||||
}
|
||||
s.writeObject(val);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -441,7 +448,8 @@ public final class StringBuilder
|
||||
throws java.io.IOException, ClassNotFoundException {
|
||||
s.defaultReadObject();
|
||||
count = s.readInt();
|
||||
value = (char[]) s.readObject();
|
||||
char[] val = (char[]) s.readObject();
|
||||
initBytes(val, 0, val.length);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2015, 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
|
||||
@ -38,11 +38,19 @@ import java.nio.charset.CodingErrorAction;
|
||||
import java.nio.charset.IllegalCharsetNameException;
|
||||
import java.nio.charset.UnsupportedCharsetException;
|
||||
import java.util.Arrays;
|
||||
import jdk.internal.HotSpotIntrinsicCandidate;
|
||||
import sun.misc.MessageUtils;
|
||||
import sun.nio.cs.HistoricallyNamedCharset;
|
||||
import sun.nio.cs.ArrayDecoder;
|
||||
import sun.nio.cs.ArrayEncoder;
|
||||
|
||||
import static java.lang.String.LATIN1;
|
||||
import static java.lang.String.UTF16;
|
||||
import static java.lang.String.COMPACT_STRINGS;
|
||||
import static java.nio.charset.StandardCharsets.ISO_8859_1;
|
||||
import static java.nio.charset.StandardCharsets.US_ASCII;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
/**
|
||||
* Utility class for string encoding and decoding.
|
||||
*/
|
||||
@ -72,23 +80,13 @@ class StringCoding {
|
||||
|
||||
// Trim the given byte array to the given length
|
||||
//
|
||||
private static byte[] safeTrim(byte[] ba, int len, Charset cs, boolean isTrusted) {
|
||||
private static byte[] safeTrim(byte[] ba, int len, boolean isTrusted) {
|
||||
if (len == ba.length && (isTrusted || System.getSecurityManager() == null))
|
||||
return ba;
|
||||
else
|
||||
return Arrays.copyOf(ba, len);
|
||||
}
|
||||
|
||||
// Trim the given char array to the given length
|
||||
//
|
||||
private static char[] safeTrim(char[] ca, int len,
|
||||
Charset cs, boolean isTrusted) {
|
||||
if (len == ca.length && (isTrusted || System.getSecurityManager() == null))
|
||||
return ca;
|
||||
else
|
||||
return Arrays.copyOf(ca, len);
|
||||
}
|
||||
|
||||
private static int scale(int len, float expansionFactor) {
|
||||
// We need to perform double, not float, arithmetic; otherwise
|
||||
// we lose low order bits when len is larger than 2**24.
|
||||
@ -117,21 +115,64 @@ class StringCoding {
|
||||
}
|
||||
}
|
||||
|
||||
static class Result {
|
||||
byte[] value;
|
||||
byte coder;
|
||||
|
||||
Result with() {
|
||||
coder = COMPACT_STRINGS ? LATIN1 : UTF16;
|
||||
value = new byte[0];
|
||||
return this;
|
||||
}
|
||||
|
||||
Result with(char[] val, int off, int len) {
|
||||
if (String.COMPACT_STRINGS) {
|
||||
byte[] bs = StringUTF16.compress(val, off, len);
|
||||
if (bs != null) {
|
||||
value = bs;
|
||||
coder = LATIN1;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
coder = UTF16;
|
||||
value = StringUTF16.toBytes(val, off, len);
|
||||
return this;
|
||||
}
|
||||
|
||||
Result with(byte[] val, byte coder) {
|
||||
this.coder = coder;
|
||||
value = val;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
private static boolean hasNegatives(byte[] ba, int off, int len) {
|
||||
for (int i = off; i < off + len; i++) {
|
||||
if (ba[i] < 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// -- Decoding --
|
||||
private static class StringDecoder {
|
||||
static class StringDecoder {
|
||||
private final String requestedCharsetName;
|
||||
private final Charset cs;
|
||||
private final boolean isASCIICompatible;
|
||||
private final CharsetDecoder cd;
|
||||
private final boolean isTrusted;
|
||||
protected final Result result;
|
||||
|
||||
private StringDecoder(Charset cs, String rcn) {
|
||||
StringDecoder(Charset cs, String rcn) {
|
||||
this.requestedCharsetName = rcn;
|
||||
this.cs = cs;
|
||||
this.cd = cs.newDecoder()
|
||||
.onMalformedInput(CodingErrorAction.REPLACE)
|
||||
.onUnmappableCharacter(CodingErrorAction.REPLACE);
|
||||
this.isTrusted = (cs.getClass().getClassLoader0() == null);
|
||||
this.result = new Result();
|
||||
this.isASCIICompatible = (cd instanceof ArrayDecoder) &&
|
||||
((ArrayDecoder)cd).isASCIICompatible();
|
||||
}
|
||||
|
||||
String charsetName() {
|
||||
@ -144,36 +185,58 @@ class StringCoding {
|
||||
return requestedCharsetName;
|
||||
}
|
||||
|
||||
char[] decode(byte[] ba, int off, int len) {
|
||||
Result decode(byte[] ba, int off, int len) {
|
||||
if (len == 0) {
|
||||
return result.with();
|
||||
}
|
||||
// fastpath for ascii compatible
|
||||
if (isASCIICompatible && !hasNegatives(ba, off, len)) {
|
||||
if (COMPACT_STRINGS) {
|
||||
return result.with(Arrays.copyOfRange(ba, off, off + len),
|
||||
LATIN1);
|
||||
} else {
|
||||
return result.with(StringLatin1.inflate(ba, off, len), UTF16);
|
||||
}
|
||||
}
|
||||
int en = scale(len, cd.maxCharsPerByte());
|
||||
char[] ca = new char[en];
|
||||
if (len == 0)
|
||||
return ca;
|
||||
if (cd instanceof ArrayDecoder) {
|
||||
int clen = ((ArrayDecoder)cd).decode(ba, off, len, ca);
|
||||
return safeTrim(ca, clen, cs, isTrusted);
|
||||
return result.with(ca, 0, clen);
|
||||
}
|
||||
cd.reset();
|
||||
ByteBuffer bb = ByteBuffer.wrap(ba, off, len);
|
||||
CharBuffer cb = CharBuffer.wrap(ca);
|
||||
try {
|
||||
CoderResult cr = cd.decode(bb, cb, true);
|
||||
if (!cr.isUnderflow())
|
||||
cr.throwException();
|
||||
cr = cd.flush(cb);
|
||||
if (!cr.isUnderflow())
|
||||
cr.throwException();
|
||||
} catch (CharacterCodingException x) {
|
||||
// Substitution is always enabled,
|
||||
// so this shouldn't happen
|
||||
throw new Error(x);
|
||||
}
|
||||
return result.with(ca, 0, cb.position());
|
||||
}
|
||||
}
|
||||
|
||||
private static class StringDecoder8859_1 extends StringDecoder {
|
||||
StringDecoder8859_1(Charset cs, String rcn) {
|
||||
super(cs, rcn);
|
||||
}
|
||||
Result decode(byte[] ba, int off, int len) {
|
||||
if (COMPACT_STRINGS) {
|
||||
return result.with(Arrays.copyOfRange(ba, off, off + len), LATIN1);
|
||||
} else {
|
||||
cd.reset();
|
||||
ByteBuffer bb = ByteBuffer.wrap(ba, off, len);
|
||||
CharBuffer cb = CharBuffer.wrap(ca);
|
||||
try {
|
||||
CoderResult cr = cd.decode(bb, cb, true);
|
||||
if (!cr.isUnderflow())
|
||||
cr.throwException();
|
||||
cr = cd.flush(cb);
|
||||
if (!cr.isUnderflow())
|
||||
cr.throwException();
|
||||
} catch (CharacterCodingException x) {
|
||||
// Substitution is always enabled,
|
||||
// so this shouldn't happen
|
||||
throw new Error(x);
|
||||
}
|
||||
return safeTrim(ca, cb.position(), cs, isTrusted);
|
||||
return result.with(StringLatin1.inflate(ba, off, len), UTF16);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static char[] decode(String charsetName, byte[] ba, int off, int len)
|
||||
static Result decode(String charsetName, byte[] ba, int off, int len)
|
||||
throws UnsupportedEncodingException
|
||||
{
|
||||
StringDecoder sd = deref(decoder);
|
||||
@ -183,8 +246,15 @@ class StringCoding {
|
||||
sd = null;
|
||||
try {
|
||||
Charset cs = lookupCharset(csn);
|
||||
if (cs != null)
|
||||
sd = new StringDecoder(cs, csn);
|
||||
if (cs != null) {
|
||||
if (cs == UTF_8) {
|
||||
sd = new StringDecoderUTF8(cs, csn);
|
||||
} else if (cs == ISO_8859_1) {
|
||||
sd = new StringDecoder8859_1(cs, csn);
|
||||
} else {
|
||||
sd = new StringDecoder(cs, csn);
|
||||
}
|
||||
}
|
||||
} catch (IllegalCharsetNameException x) {}
|
||||
if (sd == null)
|
||||
throw new UnsupportedEncodingException(csn);
|
||||
@ -193,7 +263,7 @@ class StringCoding {
|
||||
return sd.decode(ba, off, len);
|
||||
}
|
||||
|
||||
static char[] decode(Charset cs, byte[] ba, int off, int len) {
|
||||
static Result decode(Charset cs, byte[] ba, int off, int len) {
|
||||
// (1)We never cache the "external" cs, the only benefit of creating
|
||||
// an additional StringDe/Encoder object to wrap it is to share the
|
||||
// de/encode() method. These SD/E objects are short-lived, the young-gen
|
||||
@ -210,44 +280,57 @@ class StringCoding {
|
||||
// check (... && (isTrusted || SM == null || getClassLoader0())) in trim
|
||||
// but it then can be argued that the SM is null when the operation
|
||||
// is started...
|
||||
if (cs == UTF_8) {
|
||||
return StringDecoderUTF8.decode(ba, off, len, new Result());
|
||||
}
|
||||
CharsetDecoder cd = cs.newDecoder();
|
||||
// ascii fastpath
|
||||
if (cs == ISO_8859_1 || ((cd instanceof ArrayDecoder) &&
|
||||
((ArrayDecoder)cd).isASCIICompatible() &&
|
||||
!hasNegatives(ba, off, len))) {
|
||||
if (COMPACT_STRINGS) {
|
||||
return new Result().with(Arrays.copyOfRange(ba, off, off + len),
|
||||
LATIN1);
|
||||
} else {
|
||||
return new Result().with(StringLatin1.inflate(ba, off, len), UTF16);
|
||||
}
|
||||
}
|
||||
int en = scale(len, cd.maxCharsPerByte());
|
||||
char[] ca = new char[en];
|
||||
if (len == 0)
|
||||
return ca;
|
||||
boolean isTrusted = false;
|
||||
if (System.getSecurityManager() != null) {
|
||||
if (!(isTrusted = (cs.getClass().getClassLoader0() == null))) {
|
||||
ba = Arrays.copyOfRange(ba, off, off + len);
|
||||
off = 0;
|
||||
}
|
||||
if (len == 0) {
|
||||
return new Result().with();
|
||||
}
|
||||
if (System.getSecurityManager() != null &&
|
||||
cs.getClass().getClassLoader0() != null) {
|
||||
ba = Arrays.copyOfRange(ba, off, off + len);
|
||||
off = 0;
|
||||
}
|
||||
cd.onMalformedInput(CodingErrorAction.REPLACE)
|
||||
.onUnmappableCharacter(CodingErrorAction.REPLACE)
|
||||
.reset();
|
||||
|
||||
char[] ca = new char[en];
|
||||
if (cd instanceof ArrayDecoder) {
|
||||
int clen = ((ArrayDecoder)cd).decode(ba, off, len, ca);
|
||||
return safeTrim(ca, clen, cs, isTrusted);
|
||||
} else {
|
||||
ByteBuffer bb = ByteBuffer.wrap(ba, off, len);
|
||||
CharBuffer cb = CharBuffer.wrap(ca);
|
||||
try {
|
||||
CoderResult cr = cd.decode(bb, cb, true);
|
||||
if (!cr.isUnderflow())
|
||||
cr.throwException();
|
||||
cr = cd.flush(cb);
|
||||
if (!cr.isUnderflow())
|
||||
cr.throwException();
|
||||
} catch (CharacterCodingException x) {
|
||||
// Substitution is always enabled,
|
||||
// so this shouldn't happen
|
||||
throw new Error(x);
|
||||
}
|
||||
return safeTrim(ca, cb.position(), cs, isTrusted);
|
||||
return new Result().with(ca, 0, clen);
|
||||
}
|
||||
ByteBuffer bb = ByteBuffer.wrap(ba, off, len);
|
||||
CharBuffer cb = CharBuffer.wrap(ca);
|
||||
try {
|
||||
CoderResult cr = cd.decode(bb, cb, true);
|
||||
if (!cr.isUnderflow())
|
||||
cr.throwException();
|
||||
cr = cd.flush(cb);
|
||||
if (!cr.isUnderflow())
|
||||
cr.throwException();
|
||||
} catch (CharacterCodingException x) {
|
||||
// Substitution is always enabled,
|
||||
// so this shouldn't happen
|
||||
throw new Error(x);
|
||||
}
|
||||
return new Result().with(ca, 0, cb.position());
|
||||
}
|
||||
|
||||
static char[] decode(byte[] ba, int off, int len) {
|
||||
static Result decode(byte[] ba, int off, int len) {
|
||||
String csn = Charset.defaultCharset().name();
|
||||
try {
|
||||
// use charset name decode() variant which provides caching.
|
||||
@ -273,6 +356,7 @@ class StringCoding {
|
||||
private static class StringEncoder {
|
||||
private Charset cs;
|
||||
private CharsetEncoder ce;
|
||||
private final boolean isASCIICompatible;
|
||||
private final String requestedCharsetName;
|
||||
private final boolean isTrusted;
|
||||
|
||||
@ -283,6 +367,8 @@ class StringCoding {
|
||||
.onMalformedInput(CodingErrorAction.REPLACE)
|
||||
.onUnmappableCharacter(CodingErrorAction.REPLACE);
|
||||
this.isTrusted = (cs.getClass().getClassLoader0() == null);
|
||||
this.isASCIICompatible = (ce instanceof ArrayEncoder) &&
|
||||
((ArrayEncoder)ce).isASCIICompatible();
|
||||
}
|
||||
|
||||
String charsetName() {
|
||||
@ -295,36 +381,186 @@ class StringCoding {
|
||||
return requestedCharsetName;
|
||||
}
|
||||
|
||||
byte[] encode(char[] ca, int off, int len) {
|
||||
byte[] encode(byte coder, byte[] val) {
|
||||
// fastpath for ascii compatible
|
||||
if (coder == LATIN1 && isASCIICompatible &&
|
||||
!hasNegatives(val, 0, val.length)) {
|
||||
return Arrays.copyOf(val, val.length);
|
||||
}
|
||||
int len = val.length >> coder; // assume LATIN1=0/UTF16=1;
|
||||
int en = scale(len, ce.maxBytesPerChar());
|
||||
byte[] ba = new byte[en];
|
||||
if (len == 0)
|
||||
if (len == 0) {
|
||||
return ba;
|
||||
if (ce instanceof ArrayEncoder) {
|
||||
int blen = ((ArrayEncoder)ce).encode(ca, off, len, ba);
|
||||
return safeTrim(ba, blen, cs, isTrusted);
|
||||
} else {
|
||||
ce.reset();
|
||||
ByteBuffer bb = ByteBuffer.wrap(ba);
|
||||
CharBuffer cb = CharBuffer.wrap(ca, off, len);
|
||||
try {
|
||||
CoderResult cr = ce.encode(cb, bb, true);
|
||||
if (!cr.isUnderflow())
|
||||
cr.throwException();
|
||||
cr = ce.flush(bb);
|
||||
if (!cr.isUnderflow())
|
||||
cr.throwException();
|
||||
} catch (CharacterCodingException x) {
|
||||
// Substitution is always enabled,
|
||||
// so this shouldn't happen
|
||||
throw new Error(x);
|
||||
}
|
||||
return safeTrim(ba, bb.position(), cs, isTrusted);
|
||||
}
|
||||
if (ce instanceof ArrayEncoder) {
|
||||
if (!isTrusted) {
|
||||
val = Arrays.copyOf(val, val.length);
|
||||
}
|
||||
int blen = (coder == LATIN1 ) ? ((ArrayEncoder)ce).encodeFromLatin1(val, 0, len, ba)
|
||||
: ((ArrayEncoder)ce).encodeFromUTF16(val, 0, len, ba);
|
||||
if (blen != -1) {
|
||||
return safeTrim(ba, blen, isTrusted);
|
||||
}
|
||||
}
|
||||
char[] ca = (coder == LATIN1 ) ? StringLatin1.toChars(val)
|
||||
: StringUTF16.toChars(val);
|
||||
ce.reset();
|
||||
ByteBuffer bb = ByteBuffer.wrap(ba);
|
||||
CharBuffer cb = CharBuffer.wrap(ca, 0, len);
|
||||
try {
|
||||
CoderResult cr = ce.encode(cb, bb, true);
|
||||
if (!cr.isUnderflow())
|
||||
cr.throwException();
|
||||
cr = ce.flush(bb);
|
||||
if (!cr.isUnderflow())
|
||||
cr.throwException();
|
||||
} catch (CharacterCodingException x) {
|
||||
// Substitution is always enabled,
|
||||
// so this shouldn't happen
|
||||
throw new Error(x);
|
||||
}
|
||||
return safeTrim(ba, bb.position(), isTrusted);
|
||||
}
|
||||
}
|
||||
|
||||
static byte[] encode(String charsetName, char[] ca, int off, int len)
|
||||
@HotSpotIntrinsicCandidate
|
||||
private static int implEncodeISOArray(byte[] sa, int sp,
|
||||
byte[] da, int dp, int len) {
|
||||
int i = 0;
|
||||
for (; i < len; i++) {
|
||||
char c = StringUTF16.getChar(sa, sp++);
|
||||
if (c > '\u00FF')
|
||||
break;
|
||||
da[dp++] = (byte)c;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static byte[] encode8859_1(byte coder, byte[] val) {
|
||||
if (coder == LATIN1) {
|
||||
return Arrays.copyOf(val, val.length);
|
||||
}
|
||||
int len = val.length >> 1;
|
||||
byte[] dst = new byte[len];
|
||||
int dp = 0;
|
||||
int sp = 0;
|
||||
int sl = len;
|
||||
while (sp < sl) {
|
||||
int ret = implEncodeISOArray(val, sp, dst, dp, len);
|
||||
sp = sp + ret;
|
||||
dp = dp + ret;
|
||||
if (ret != len) {
|
||||
char c = StringUTF16.getChar(val, sp++);
|
||||
if (Character.isHighSurrogate(c) && sp < sl &&
|
||||
Character.isLowSurrogate(StringUTF16.getChar(val, sp))) {
|
||||
sp++;
|
||||
}
|
||||
dst[dp++] = '?';
|
||||
len = sl - sp;
|
||||
}
|
||||
}
|
||||
if (dp == dst.length) {
|
||||
return dst;
|
||||
}
|
||||
return Arrays.copyOf(dst, dp);
|
||||
}
|
||||
|
||||
static byte[] encodeASCII(byte coder, byte[] val) {
|
||||
if (coder == LATIN1) {
|
||||
byte[] dst = new byte[val.length];
|
||||
for (int i = 0; i < val.length; i++) {
|
||||
if (val[i] < 0) {
|
||||
dst[i] = '?';
|
||||
} else {
|
||||
dst[i] = val[i];
|
||||
}
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
int len = val.length >> 1;
|
||||
byte[] dst = new byte[len];
|
||||
int dp = 0;
|
||||
for (int i = 0; i < len; i++) {
|
||||
char c = StringUTF16.getChar(val, i);
|
||||
if (c < 0x80) {
|
||||
dst[dp++] = (byte)c;
|
||||
continue;
|
||||
}
|
||||
if (Character.isHighSurrogate(c) && i + 1 < len &&
|
||||
Character.isLowSurrogate(StringUTF16.getChar(val, i + 1))) {
|
||||
i++;
|
||||
}
|
||||
dst[dp++] = '?';
|
||||
}
|
||||
if (len == dp) {
|
||||
return dst;
|
||||
}
|
||||
return Arrays.copyOf(dst, dp);
|
||||
}
|
||||
|
||||
static byte[] encodeUTF8(byte coder, byte[] val) {
|
||||
int dp = 0;
|
||||
byte[] dst;
|
||||
if (coder == LATIN1) {
|
||||
dst = new byte[val.length << 1];
|
||||
for (int sp = 0; sp < val.length; sp++) {
|
||||
byte c = val[sp];
|
||||
if (c < 0) {
|
||||
dst[dp++] = (byte)(0xc0 | ((c & 0xff) >> 6));
|
||||
dst[dp++] = (byte)(0x80 | (c & 0x3f));
|
||||
} else {
|
||||
dst[dp++] = c;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int sp = 0;
|
||||
int sl = val.length >> 1;
|
||||
dst = new byte[sl * 3];
|
||||
char c;
|
||||
while (sp < sl && (c = StringUTF16.getChar(val, sp)) < '\u0080') {
|
||||
// ascii fast loop;
|
||||
dst[dp++] = (byte)c;
|
||||
sp++;
|
||||
}
|
||||
while (sp < sl) {
|
||||
c = StringUTF16.getChar(val, sp++);
|
||||
if (c < 0x80) {
|
||||
dst[dp++] = (byte)c;
|
||||
} else if (c < 0x800) {
|
||||
dst[dp++] = (byte)(0xc0 | (c >> 6));
|
||||
dst[dp++] = (byte)(0x80 | (c & 0x3f));
|
||||
} else if (Character.isSurrogate(c)) {
|
||||
int uc = -1;
|
||||
char c2;
|
||||
if (Character.isHighSurrogate(c) && sp < sl &&
|
||||
Character.isLowSurrogate(c2 = StringUTF16.getChar(val, sp))) {
|
||||
uc = Character.toCodePoint(c, c2);
|
||||
}
|
||||
if (uc < 0) {
|
||||
dst[dp++] = '?';
|
||||
} else {
|
||||
dst[dp++] = (byte)(0xf0 | ((uc >> 18)));
|
||||
dst[dp++] = (byte)(0x80 | ((uc >> 12) & 0x3f));
|
||||
dst[dp++] = (byte)(0x80 | ((uc >> 6) & 0x3f));
|
||||
dst[dp++] = (byte)(0x80 | (uc & 0x3f));
|
||||
sp++; // 2 chars
|
||||
}
|
||||
} else {
|
||||
// 3 bytes, 16 bits
|
||||
dst[dp++] = (byte)(0xe0 | ((c >> 12)));
|
||||
dst[dp++] = (byte)(0x80 | ((c >> 6) & 0x3f));
|
||||
dst[dp++] = (byte)(0x80 | (c & 0x3f));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dp == dst.length) {
|
||||
return dst;
|
||||
}
|
||||
return Arrays.copyOf(dst, dp);
|
||||
}
|
||||
|
||||
static byte[] encode(String charsetName, byte coder, byte[] val)
|
||||
throws UnsupportedEncodingException
|
||||
{
|
||||
StringEncoder se = deref(encoder);
|
||||
@ -334,62 +570,88 @@ class StringCoding {
|
||||
se = null;
|
||||
try {
|
||||
Charset cs = lookupCharset(csn);
|
||||
if (cs != null)
|
||||
if (cs != null) {
|
||||
if (cs == UTF_8) {
|
||||
return encodeUTF8(coder, val);
|
||||
} else if (cs == ISO_8859_1) {
|
||||
return encode8859_1(coder, val);
|
||||
} else if (cs == US_ASCII) {
|
||||
return encodeASCII(coder, val);
|
||||
}
|
||||
se = new StringEncoder(cs, csn);
|
||||
}
|
||||
} catch (IllegalCharsetNameException x) {}
|
||||
if (se == null)
|
||||
if (se == null) {
|
||||
throw new UnsupportedEncodingException (csn);
|
||||
}
|
||||
set(encoder, se);
|
||||
}
|
||||
return se.encode(ca, off, len);
|
||||
return se.encode(coder, val);
|
||||
}
|
||||
|
||||
static byte[] encode(Charset cs, char[] ca, int off, int len) {
|
||||
static byte[] encode(Charset cs, byte coder, byte[] val) {
|
||||
if (cs == UTF_8) {
|
||||
return encodeUTF8(coder, val);
|
||||
} else if (cs == ISO_8859_1) {
|
||||
return encode8859_1(coder, val);
|
||||
} else if (cs == US_ASCII) {
|
||||
return encodeASCII(coder, val);
|
||||
}
|
||||
CharsetEncoder ce = cs.newEncoder();
|
||||
// fastpath for ascii compatible
|
||||
if (coder == LATIN1 && (((ce instanceof ArrayEncoder) &&
|
||||
((ArrayEncoder)ce).isASCIICompatible() &&
|
||||
!hasNegatives(val, 0, val.length)))) {
|
||||
return Arrays.copyOf(val, val.length);
|
||||
}
|
||||
int len = val.length >> coder; // assume LATIN1=0/UTF16=1;
|
||||
int en = scale(len, ce.maxBytesPerChar());
|
||||
byte[] ba = new byte[en];
|
||||
if (len == 0)
|
||||
if (len == 0) {
|
||||
return ba;
|
||||
boolean isTrusted = false;
|
||||
if (System.getSecurityManager() != null) {
|
||||
if (!(isTrusted = (cs.getClass().getClassLoader0() == null))) {
|
||||
ca = Arrays.copyOfRange(ca, off, off + len);
|
||||
off = 0;
|
||||
}
|
||||
}
|
||||
boolean isTrusted = System.getSecurityManager() == null ||
|
||||
cs.getClass().getClassLoader0() == null;
|
||||
ce.onMalformedInput(CodingErrorAction.REPLACE)
|
||||
.onUnmappableCharacter(CodingErrorAction.REPLACE)
|
||||
.reset();
|
||||
if (ce instanceof ArrayEncoder) {
|
||||
int blen = ((ArrayEncoder)ce).encode(ca, off, len, ba);
|
||||
return safeTrim(ba, blen, cs, isTrusted);
|
||||
} else {
|
||||
ByteBuffer bb = ByteBuffer.wrap(ba);
|
||||
CharBuffer cb = CharBuffer.wrap(ca, off, len);
|
||||
try {
|
||||
CoderResult cr = ce.encode(cb, bb, true);
|
||||
if (!cr.isUnderflow())
|
||||
cr.throwException();
|
||||
cr = ce.flush(bb);
|
||||
if (!cr.isUnderflow())
|
||||
cr.throwException();
|
||||
} catch (CharacterCodingException x) {
|
||||
throw new Error(x);
|
||||
if (!isTrusted) {
|
||||
val = Arrays.copyOf(val, val.length);
|
||||
}
|
||||
int blen = (coder == LATIN1 ) ? ((ArrayEncoder)ce).encodeFromLatin1(val, 0, len, ba)
|
||||
: ((ArrayEncoder)ce).encodeFromUTF16(val, 0, len, ba);
|
||||
if (blen != -1) {
|
||||
return safeTrim(ba, blen, isTrusted);
|
||||
}
|
||||
return safeTrim(ba, bb.position(), cs, isTrusted);
|
||||
}
|
||||
char[] ca = (coder == LATIN1 ) ? StringLatin1.toChars(val)
|
||||
: StringUTF16.toChars(val);
|
||||
ByteBuffer bb = ByteBuffer.wrap(ba);
|
||||
CharBuffer cb = CharBuffer.wrap(ca, 0, len);
|
||||
try {
|
||||
CoderResult cr = ce.encode(cb, bb, true);
|
||||
if (!cr.isUnderflow())
|
||||
cr.throwException();
|
||||
cr = ce.flush(bb);
|
||||
if (!cr.isUnderflow())
|
||||
cr.throwException();
|
||||
} catch (CharacterCodingException x) {
|
||||
throw new Error(x);
|
||||
}
|
||||
return safeTrim(ba, bb.position(), isTrusted);
|
||||
}
|
||||
|
||||
static byte[] encode(char[] ca, int off, int len) {
|
||||
static byte[] encode(byte coder, byte[] val) {
|
||||
String csn = Charset.defaultCharset().name();
|
||||
try {
|
||||
// use charset name encode() variant which provides caching.
|
||||
return encode(csn, ca, off, len);
|
||||
return encode(csn, coder, val);
|
||||
} catch (UnsupportedEncodingException x) {
|
||||
warnUnsupportedCharset(csn);
|
||||
}
|
||||
try {
|
||||
return encode("ISO-8859-1", ca, off, len);
|
||||
return encode("ISO-8859-1", coder, val);
|
||||
} catch (UnsupportedEncodingException x) {
|
||||
// If this code is hit during VM initialization, MessageUtils is
|
||||
// the only way we will be able to get any kind of error message.
|
||||
|
235
jdk/src/java.base/share/classes/java/lang/StringDecoderUTF8.java
Normal file
235
jdk/src/java.base/share/classes/java/lang/StringDecoderUTF8.java
Normal file
@ -0,0 +1,235 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.lang;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static java.lang.String.LATIN1;
|
||||
import static java.lang.String.UTF16;
|
||||
import static java.lang.String.COMPACT_STRINGS;
|
||||
import static java.lang.Character.isSurrogate;
|
||||
import static java.lang.Character.highSurrogate;
|
||||
import static java.lang.Character.lowSurrogate;
|
||||
import static java.lang.Character.isSupplementaryCodePoint;
|
||||
import static java.lang.StringUTF16.putChar;
|
||||
|
||||
class StringDecoderUTF8 extends StringCoding.StringDecoder {
|
||||
|
||||
StringDecoderUTF8(Charset cs, String rcn) {
|
||||
super(cs, rcn);
|
||||
}
|
||||
|
||||
private static boolean isNotContinuation(int b) {
|
||||
return (b & 0xc0) != 0x80;
|
||||
}
|
||||
|
||||
private static boolean isMalformed3(int b1, int b2, int b3) {
|
||||
return (b1 == (byte)0xe0 && (b2 & 0xe0) == 0x80) ||
|
||||
(b2 & 0xc0) != 0x80 || (b3 & 0xc0) != 0x80;
|
||||
}
|
||||
|
||||
private static boolean isMalformed3_2(int b1, int b2) {
|
||||
return (b1 == (byte)0xe0 && (b2 & 0xe0) == 0x80) ||
|
||||
(b2 & 0xc0) != 0x80;
|
||||
}
|
||||
|
||||
private static boolean isMalformed4(int b2, int b3, int b4) {
|
||||
return (b2 & 0xc0) != 0x80 || (b3 & 0xc0) != 0x80 ||
|
||||
(b4 & 0xc0) != 0x80;
|
||||
}
|
||||
|
||||
private static boolean isMalformed4_2(int b1, int b2) {
|
||||
return (b1 == 0xf0 && (b2 < 0x90 || b2 > 0xbf)) ||
|
||||
(b1 == 0xf4 && (b2 & 0xf0) != 0x80) ||
|
||||
(b2 & 0xc0) != 0x80;
|
||||
}
|
||||
|
||||
private static boolean isMalformed4_3(int b3) {
|
||||
return (b3 & 0xc0) != 0x80;
|
||||
}
|
||||
|
||||
// for nb == 3/4
|
||||
private static int malformedN(byte[] src, int sp, int nb) {
|
||||
if (nb == 3) {
|
||||
int b1 = src[sp++];
|
||||
int b2 = src[sp++]; // no need to lookup b3
|
||||
return ((b1 == (byte)0xe0 && (b2 & 0xe0) == 0x80) ||
|
||||
isNotContinuation(b2)) ? 1 : 2;
|
||||
} else if (nb == 4) { // we don't care the speed here
|
||||
int b1 = src[sp++] & 0xff;
|
||||
int b2 = src[sp++] & 0xff;
|
||||
if (b1 > 0xf4 ||
|
||||
(b1 == 0xf0 && (b2 < 0x90 || b2 > 0xbf)) ||
|
||||
(b1 == 0xf4 && (b2 & 0xf0) != 0x80) ||
|
||||
isNotContinuation(b2))
|
||||
return 1;
|
||||
if (isNotContinuation(src[sp++]))
|
||||
return 2;
|
||||
return 3;
|
||||
}
|
||||
assert false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static char repl = '\ufffd';
|
||||
|
||||
StringCoding.Result decode(byte[] src, int sp, int len) {
|
||||
return decode(src, sp, len, result);
|
||||
}
|
||||
|
||||
static StringCoding.Result decode(byte[] src, int sp, int len,
|
||||
StringCoding.Result ret) {
|
||||
int sl = sp + len;
|
||||
byte[] dst = new byte[len];
|
||||
int dp = 0;
|
||||
if (COMPACT_STRINGS) { // Latin1 only loop
|
||||
while (sp < sl) {
|
||||
int b1 = src[sp];
|
||||
if (b1 >= 0) {
|
||||
dst[dp++] = (byte)b1;
|
||||
sp++;
|
||||
continue;
|
||||
}
|
||||
if ((b1 == (byte)0xc2 || b1 == (byte)0xc3) &&
|
||||
sp + 1 < sl) {
|
||||
int b2 = src[sp + 1];
|
||||
if (!isNotContinuation(b2)) {
|
||||
dst[dp++] = (byte)(((b1 << 6) ^ b2)^
|
||||
(((byte) 0xC0 << 6) ^
|
||||
((byte) 0x80 << 0)));
|
||||
sp += 2;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// anything not a latin1, including the repl
|
||||
// we have to go with the utf16
|
||||
break;
|
||||
}
|
||||
if (sp == sl) {
|
||||
if (dp != dst.length) {
|
||||
dst = Arrays.copyOf(dst, dp);
|
||||
}
|
||||
return ret.with(dst, LATIN1);
|
||||
}
|
||||
}
|
||||
if (dp == 0) {
|
||||
dst = new byte[len << 1];
|
||||
} else {
|
||||
byte[] buf = new byte[len << 1];
|
||||
StringLatin1.inflate(dst, 0, buf, 0, dp);
|
||||
dst = buf;
|
||||
}
|
||||
while (sp < sl) {
|
||||
int b1 = src[sp++];
|
||||
if (b1 >= 0) {
|
||||
putChar(dst, dp++, (char) b1);
|
||||
} else if ((b1 >> 5) == -2 && (b1 & 0x1e) != 0) {
|
||||
if (sp < sl) {
|
||||
int b2 = src[sp++];
|
||||
if (isNotContinuation(b2)) {
|
||||
putChar(dst, dp++, repl);
|
||||
sp--;
|
||||
} else {
|
||||
putChar(dst, dp++, (char)(((b1 << 6) ^ b2)^
|
||||
(((byte) 0xC0 << 6) ^
|
||||
((byte) 0x80 << 0))));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
putChar(dst, dp++, repl);
|
||||
break;
|
||||
} else if ((b1 >> 4) == -2) {
|
||||
if (sp + 1 < sl) {
|
||||
int b2 = src[sp++];
|
||||
int b3 = src[sp++];
|
||||
if (isMalformed3(b1, b2, b3)) {
|
||||
putChar(dst, dp++, repl);
|
||||
sp -= 3;
|
||||
sp += malformedN(src, sp, 3);
|
||||
} else {
|
||||
char c = (char)((b1 << 12) ^
|
||||
(b2 << 6) ^
|
||||
(b3 ^
|
||||
(((byte) 0xE0 << 12) ^
|
||||
((byte) 0x80 << 6) ^
|
||||
((byte) 0x80 << 0))));
|
||||
putChar(dst, dp++, isSurrogate(c) ? repl : c);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (sp < sl && isMalformed3_2(b1, src[sp])) {
|
||||
putChar(dst, dp++, repl);
|
||||
continue;
|
||||
}
|
||||
putChar(dst, dp++, repl);
|
||||
break;
|
||||
} else if ((b1 >> 3) == -2) {
|
||||
if (sp + 2 < sl) {
|
||||
int b2 = src[sp++];
|
||||
int b3 = src[sp++];
|
||||
int b4 = src[sp++];
|
||||
int uc = ((b1 << 18) ^
|
||||
(b2 << 12) ^
|
||||
(b3 << 6) ^
|
||||
(b4 ^
|
||||
(((byte) 0xF0 << 18) ^
|
||||
((byte) 0x80 << 12) ^
|
||||
((byte) 0x80 << 6) ^
|
||||
((byte) 0x80 << 0))));
|
||||
if (isMalformed4(b2, b3, b4) ||
|
||||
!isSupplementaryCodePoint(uc)) { // shortest form check
|
||||
putChar(dst, dp++, repl);
|
||||
sp -= 4;
|
||||
sp += malformedN(src, sp, 4);
|
||||
} else {
|
||||
putChar(dst, dp++, highSurrogate(uc));
|
||||
putChar(dst, dp++, lowSurrogate(uc));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
b1 &= 0xff;
|
||||
if (b1 > 0xf4 ||
|
||||
sp < sl && isMalformed4_2(b1, src[sp] & 0xff)) {
|
||||
putChar(dst, dp++, repl);
|
||||
continue;
|
||||
}
|
||||
sp++;
|
||||
putChar(dst, dp++, repl);
|
||||
if (sp < sl && isMalformed4_3(src[sp])) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
putChar(dst, dp++, repl);
|
||||
}
|
||||
}
|
||||
if (dp != len) {
|
||||
dst = Arrays.copyOf(dst, dp << 1);
|
||||
}
|
||||
return ret.with(dst, UTF16);
|
||||
}
|
||||
}
|
600
jdk/src/java.base/share/classes/java/lang/StringLatin1.java
Normal file
600
jdk/src/java.base/share/classes/java/lang/StringLatin1.java
Normal file
@ -0,0 +1,600 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.lang;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Spliterator;
|
||||
import java.util.function.IntConsumer;
|
||||
import java.util.stream.IntStream;
|
||||
import jdk.internal.HotSpotIntrinsicCandidate;
|
||||
|
||||
import static java.lang.String.LATIN1;
|
||||
import static java.lang.String.UTF16;
|
||||
import static java.lang.String.checkOffset;
|
||||
|
||||
final class StringLatin1 {
|
||||
|
||||
public static char charAt(byte[] value, int index) {
|
||||
if (index < 0 || index >= value.length) {
|
||||
throw new StringIndexOutOfBoundsException(index);
|
||||
}
|
||||
return (char)(value[index] & 0xff);
|
||||
}
|
||||
|
||||
public static boolean canEncode(int cp) {
|
||||
return cp >>> 8 == 0;
|
||||
}
|
||||
|
||||
public static int length(byte[] value) {
|
||||
return value.length;
|
||||
}
|
||||
|
||||
public static int codePointAt(byte[] value, int index, int end) {
|
||||
return value[index] & 0xff;
|
||||
}
|
||||
|
||||
public static int codePointBefore(byte[] value, int index) {
|
||||
return value[index - 1] & 0xff;
|
||||
}
|
||||
|
||||
public static int codePointCount(byte[] value, int beginIndex, int endIndex) {
|
||||
return endIndex - beginIndex;
|
||||
}
|
||||
|
||||
public static char[] toChars(byte[] value) {
|
||||
char[] dst = new char[value.length];
|
||||
inflate(value, 0, dst, 0, value.length);
|
||||
return dst;
|
||||
}
|
||||
|
||||
public static byte[] inflate(byte[] value, int off, int len) {
|
||||
byte[] ret = StringUTF16.newBytesFor(len);
|
||||
inflate(value, off, ret, 0, len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static void getChars(byte[] value, int srcBegin, int srcEnd, char dst[], int dstBegin) {
|
||||
inflate(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
|
||||
}
|
||||
|
||||
public static void getBytes(byte[] value, int srcBegin, int srcEnd, byte dst[], int dstBegin) {
|
||||
System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
|
||||
}
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
public static boolean equals(byte[] value, byte[] other) {
|
||||
if (value.length == other.length) {
|
||||
for (int i = 0; i < value.length; i++) {
|
||||
if (value[i] != other[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
public static int compareTo(byte[] value, byte[] other) {
|
||||
int len1 = value.length;
|
||||
int len2 = other.length;
|
||||
int lim = Math.min(len1, len2);
|
||||
for (int k = 0; k < lim; k++) {
|
||||
if (value[k] != other[k]) {
|
||||
return getChar(value, k) - getChar(other, k);
|
||||
}
|
||||
}
|
||||
return len1 - len2;
|
||||
}
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
public static int compareToUTF16(byte[] value, byte[] other) {
|
||||
int len1 = length(value);
|
||||
int len2 = StringUTF16.length(other);
|
||||
int lim = Math.min(len1, len2);
|
||||
for (int k = 0; k < lim; k++) {
|
||||
char c1 = getChar(value, k);
|
||||
char c2 = StringUTF16.getChar(other, k);
|
||||
if (c1 != c2) {
|
||||
return c1 - c2;
|
||||
}
|
||||
}
|
||||
return len1 - len2;
|
||||
}
|
||||
|
||||
public static int hashCode(byte[] value) {
|
||||
int h = 0;
|
||||
for (byte v : value) {
|
||||
h = 31 * h + (v & 0xff);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
public static int indexOf(byte[] value, int ch, int fromIndex) {
|
||||
if (!canEncode(ch)) {
|
||||
return -1;
|
||||
}
|
||||
int max = value.length;
|
||||
if (fromIndex < 0) {
|
||||
fromIndex = 0;
|
||||
} else if (fromIndex >= max) {
|
||||
// Note: fromIndex might be near -1>>>1.
|
||||
return -1;
|
||||
}
|
||||
byte c = (byte)ch;
|
||||
for (int i = fromIndex; i < max; i++) {
|
||||
if (value[i] == c) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
public static int indexOf(byte[] value, byte[] str) {
|
||||
if (str.length == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (value.length == 0) {
|
||||
return -1;
|
||||
}
|
||||
return indexOf(value, value.length, str, str.length, 0);
|
||||
}
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
public static int indexOf(byte[] value, int valueCount, byte[] str, int strCount, int fromIndex) {
|
||||
byte first = str[0];
|
||||
int max = (valueCount - strCount);
|
||||
for (int i = fromIndex; i <= max; i++) {
|
||||
// Look for first character.
|
||||
if (value[i] != first) {
|
||||
while (++i <= max && value[i] != first);
|
||||
}
|
||||
// Found first character, now look at the rest of value
|
||||
if (i <= max) {
|
||||
int j = i + 1;
|
||||
int end = j + strCount - 1;
|
||||
for (int k = 1; j < end && value[j] == str[k]; j++, k++);
|
||||
if (j == end) {
|
||||
// Found whole string.
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static int lastIndexOf(byte[] src, int srcCount,
|
||||
byte[] tgt, int tgtCount, int fromIndex) {
|
||||
int min = tgtCount - 1;
|
||||
int i = min + fromIndex;
|
||||
int strLastIndex = tgtCount - 1;
|
||||
char strLastChar = (char)(tgt[strLastIndex] & 0xff);
|
||||
|
||||
startSearchForLastChar:
|
||||
while (true) {
|
||||
while (i >= min && (src[i] & 0xff) != strLastChar) {
|
||||
i--;
|
||||
}
|
||||
if (i < min) {
|
||||
return -1;
|
||||
}
|
||||
int j = i - 1;
|
||||
int start = j - strLastIndex;
|
||||
int k = strLastIndex - 1;
|
||||
while (j > start) {
|
||||
if ((src[j--] & 0xff) != (tgt[k--] & 0xff)) {
|
||||
i--;
|
||||
continue startSearchForLastChar;
|
||||
}
|
||||
}
|
||||
return start + 1;
|
||||
}
|
||||
}
|
||||
|
||||
public static int lastIndexOf(final byte[] value, int ch, int fromIndex) {
|
||||
if (!canEncode(ch)) {
|
||||
return -1;
|
||||
}
|
||||
int off = Math.min(fromIndex, value.length - 1);
|
||||
for (; off >= 0; off--) {
|
||||
if (value[off] == (byte)ch) {
|
||||
return off;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static String replace(byte[] value, char oldChar, char newChar) {
|
||||
if (canEncode(oldChar)) {
|
||||
int len = value.length;
|
||||
int i = -1;
|
||||
while (++i < len) {
|
||||
if (value[i] == (byte)oldChar) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < len) {
|
||||
if (canEncode(newChar)) {
|
||||
byte buf[] = new byte[len];
|
||||
for (int j = 0; j < i; j++) { // TBD arraycopy?
|
||||
buf[j] = value[j];
|
||||
}
|
||||
while (i < len) {
|
||||
byte c = value[i];
|
||||
buf[i] = (c == (byte)oldChar) ? (byte)newChar : c;
|
||||
i++;
|
||||
}
|
||||
return new String(buf, LATIN1);
|
||||
} else {
|
||||
byte[] buf = StringUTF16.newBytesFor(len);
|
||||
// inflate from latin1 to UTF16
|
||||
inflate(value, 0, buf, 0, i);
|
||||
while (i < len) {
|
||||
char c = (char)(value[i] & 0xff);
|
||||
StringUTF16.putChar(buf, i, (c == oldChar) ? newChar : c);
|
||||
i++;
|
||||
}
|
||||
return new String(buf, UTF16);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null; // for string to return this;
|
||||
}
|
||||
|
||||
// case insensitive
|
||||
public static boolean regionMatchesCI(byte[] value, int toffset,
|
||||
byte[] other, int ooffset, int len) {
|
||||
int last = toffset + len;
|
||||
while (toffset < last) {
|
||||
char c1 = (char)(value[toffset++] & 0xff);
|
||||
char c2 = (char)(other[ooffset++] & 0xff);
|
||||
if (c1 == c2) {
|
||||
continue;
|
||||
}
|
||||
char u1 = Character.toUpperCase(c1);
|
||||
char u2 = Character.toUpperCase(c2);
|
||||
if (u1 == u2) {
|
||||
continue;
|
||||
}
|
||||
if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean regionMatchesCI_UTF16(byte[] value, int toffset,
|
||||
byte[] other, int ooffset, int len) {
|
||||
int last = toffset + len;
|
||||
while (toffset < last) {
|
||||
char c1 = (char)(value[toffset++] & 0xff);
|
||||
char c2 = StringUTF16.getChar(other, ooffset++);
|
||||
if (c1 == c2) {
|
||||
continue;
|
||||
}
|
||||
char u1 = Character.toUpperCase(c1);
|
||||
char u2 = Character.toUpperCase(c2);
|
||||
if (u1 == u2) {
|
||||
continue;
|
||||
}
|
||||
if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static String toLowerCase(String str, byte[] value, Locale locale) {
|
||||
if (locale == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
int first;
|
||||
final int len = value.length;
|
||||
// Now check if there are any characters that need to be changed, or are surrogate
|
||||
for (first = 0 ; first < len; first++) {
|
||||
int cp = value[first] & 0xff;
|
||||
if (cp != Character.toLowerCase(cp)) { // no need to check Character.ERROR
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (first == len)
|
||||
return str;
|
||||
String lang = locale.getLanguage();
|
||||
if (lang == "tr" || lang == "az" || lang == "lt") {
|
||||
return toLowerCaseEx(str, value, first, locale, true);
|
||||
}
|
||||
byte[] result = new byte[len];
|
||||
System.arraycopy(value, 0, result, 0, first); // Just copy the first few
|
||||
// lowerCase characters.
|
||||
for (int i = first; i < len; i++) {
|
||||
int cp = value[i] & 0xff;
|
||||
cp = Character.toLowerCase(cp);
|
||||
if (!canEncode(cp)) { // not a latin1 character
|
||||
return toLowerCaseEx(str, value, first, locale, false);
|
||||
}
|
||||
result[i] = (byte)cp;
|
||||
}
|
||||
return new String(result, LATIN1);
|
||||
}
|
||||
|
||||
private static String toLowerCaseEx(String str, byte[] value,
|
||||
int first, Locale locale, boolean localeDependent)
|
||||
{
|
||||
byte[] result = StringUTF16.newBytesFor(value.length);
|
||||
int resultOffset = 0;
|
||||
for (int i = 0; i < first; i++) {
|
||||
StringUTF16.putChar(result, resultOffset++, value[i] & 0xff);
|
||||
}
|
||||
for (int i = first; i < value.length; i++) {
|
||||
int srcChar = value[i] & 0xff;
|
||||
int lowerChar;
|
||||
char[] lowerCharArray;
|
||||
if (localeDependent) {
|
||||
lowerChar = ConditionalSpecialCasing.toLowerCaseEx(str, i, locale);
|
||||
} else {
|
||||
lowerChar = Character.toLowerCase(srcChar);
|
||||
}
|
||||
if (Character.isBmpCodePoint(lowerChar)) { // Character.ERROR is not a bmp
|
||||
StringUTF16.putChar(result, resultOffset++, lowerChar);
|
||||
} else {
|
||||
if (lowerChar == Character.ERROR) {
|
||||
lowerCharArray = ConditionalSpecialCasing.toLowerCaseCharArray(str, i, locale);
|
||||
} else {
|
||||
lowerCharArray = Character.toChars(lowerChar);
|
||||
}
|
||||
/* Grow result if needed */
|
||||
int mapLen = lowerCharArray.length;
|
||||
if (mapLen > 1) {
|
||||
byte[] result2 = StringUTF16.newBytesFor((result.length >> 1) + mapLen - 1);
|
||||
System.arraycopy(result, 0, result2, 0, resultOffset << 1);
|
||||
result = result2;
|
||||
}
|
||||
for (int x = 0; x < mapLen; ++x) {
|
||||
StringUTF16.putChar(result, resultOffset++, lowerCharArray[x]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return StringUTF16.newString(result, 0, resultOffset);
|
||||
}
|
||||
|
||||
public static String toUpperCase(String str, byte[] value, Locale locale) {
|
||||
if (locale == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
int first;
|
||||
final int len = value.length;
|
||||
|
||||
// Now check if there are any characters that need to be changed, or are surrogate
|
||||
for (first = 0 ; first < len; first++ ) {
|
||||
int cp = value[first] & 0xff;
|
||||
if (cp != Character.toUpperCaseEx(cp)) { // no need to check Character.ERROR
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (first == len) {
|
||||
return str;
|
||||
}
|
||||
String lang = locale.getLanguage();
|
||||
if (lang == "tr" || lang == "az" || lang == "lt") {
|
||||
return toUpperCaseEx(str, value, first, locale, true);
|
||||
}
|
||||
byte[] result = new byte[len];
|
||||
System.arraycopy(value, 0, result, 0, first); // Just copy the first few
|
||||
// upperCase characters.
|
||||
for (int i = first; i < len; i++) {
|
||||
int cp = value[i] & 0xff;
|
||||
cp = Character.toUpperCaseEx(cp);
|
||||
if (!canEncode(cp)) { // not a latin1 character
|
||||
return toUpperCaseEx(str, value, first, locale, false);
|
||||
}
|
||||
result[i] = (byte)cp;
|
||||
}
|
||||
return new String(result, LATIN1);
|
||||
}
|
||||
|
||||
private static String toUpperCaseEx(String str, byte[] value,
|
||||
int first, Locale locale, boolean localeDependent)
|
||||
{
|
||||
byte[] result = StringUTF16.newBytesFor(value.length);
|
||||
int resultOffset = 0;
|
||||
for (int i = 0; i < first; i++) {
|
||||
StringUTF16.putChar(result, resultOffset++, value[i] & 0xff);
|
||||
}
|
||||
for (int i = first; i < value.length; i++) {
|
||||
int srcChar = value[i] & 0xff;
|
||||
int upperChar;
|
||||
char[] upperCharArray;
|
||||
if (localeDependent) {
|
||||
upperChar = ConditionalSpecialCasing.toUpperCaseEx(str, i, locale);
|
||||
} else {
|
||||
upperChar = Character.toUpperCaseEx(srcChar);
|
||||
}
|
||||
if (Character.isBmpCodePoint(upperChar)) {
|
||||
StringUTF16.putChar(result, resultOffset++, upperChar);
|
||||
} else {
|
||||
if (upperChar == Character.ERROR) {
|
||||
if (localeDependent) {
|
||||
upperCharArray =
|
||||
ConditionalSpecialCasing.toUpperCaseCharArray(str, i, locale);
|
||||
} else {
|
||||
upperCharArray = Character.toUpperCaseCharArray(srcChar);
|
||||
}
|
||||
} else {
|
||||
upperCharArray = Character.toChars(upperChar);
|
||||
}
|
||||
/* Grow result if needed */
|
||||
int mapLen = upperCharArray.length;
|
||||
if (mapLen > 1) {
|
||||
byte[] result2 = StringUTF16.newBytesFor((result.length >> 1) + mapLen - 1);
|
||||
System.arraycopy(result, 0, result2, 0, resultOffset << 1);
|
||||
result = result2;
|
||||
}
|
||||
for (int x = 0; x < mapLen; ++x) {
|
||||
StringUTF16.putChar(result, resultOffset++, upperCharArray[x]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return StringUTF16.newString(result, 0, resultOffset);
|
||||
}
|
||||
|
||||
public static String trim(byte[] value) {
|
||||
int len = value.length;
|
||||
int st = 0;
|
||||
while ((st < len) && ((value[st] & 0xff) <= ' ')) {
|
||||
st++;
|
||||
}
|
||||
while ((st < len) && ((value[len - 1] & 0xff) <= ' ')) {
|
||||
len--;
|
||||
}
|
||||
return ((st > 0) || (len < value.length)) ?
|
||||
newString(value, st, len - st) : null;
|
||||
}
|
||||
|
||||
public static void putChar(byte[] val, int index, int c) {
|
||||
//assert (canEncode(c));
|
||||
val[index] = (byte)(c);
|
||||
}
|
||||
|
||||
public static char getChar(byte[] val, int index) {
|
||||
return (char)(val[index] & 0xff);
|
||||
}
|
||||
|
||||
public static byte[] toBytes(int[] val, int off, int len) {
|
||||
byte[] ret = new byte[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
int cp = val[off++];
|
||||
if (!canEncode(cp)) {
|
||||
return null;
|
||||
}
|
||||
ret[i] = (byte)cp;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static byte[] toBytes(char c) {
|
||||
return new byte[] { (byte)c };
|
||||
}
|
||||
|
||||
public static String newString(byte[] val, int index, int len) {
|
||||
return new String(Arrays.copyOfRange(val, index, index + len),
|
||||
LATIN1);
|
||||
}
|
||||
|
||||
public static void fillNull(byte[] val, int index, int end) {
|
||||
Arrays.fill(val, index, end, (byte)0);
|
||||
}
|
||||
|
||||
// inflatedCopy byte[] -> char[]
|
||||
@HotSpotIntrinsicCandidate
|
||||
private static void inflate(byte[] src, int srcOff, char[] dst, int dstOff, int len) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
dst[dstOff++] = (char)(src[srcOff++] & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
// inflatedCopy byte[] -> byte[]
|
||||
@HotSpotIntrinsicCandidate
|
||||
public static void inflate(byte[] src, int srcOff, byte[] dst, int dstOff, int len) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
StringUTF16.putChar(dst, dstOff++, src[srcOff++] & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
static class CharsSpliterator implements Spliterator.OfInt {
|
||||
private final byte[] array;
|
||||
private int index; // current index, modified on advance/split
|
||||
private final int fence; // one past last index
|
||||
private final int cs;
|
||||
|
||||
CharsSpliterator(byte[] array, int acs) {
|
||||
this(array, 0, array.length, acs);
|
||||
}
|
||||
|
||||
CharsSpliterator(byte[] array, int origin, int fence, int acs) {
|
||||
this.array = array;
|
||||
this.index = origin;
|
||||
this.fence = fence;
|
||||
this.cs = acs | Spliterator.ORDERED | Spliterator.SIZED
|
||||
| Spliterator.SUBSIZED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OfInt trySplit() {
|
||||
int lo = index, mid = (lo + fence) >>> 1;
|
||||
return (lo >= mid)
|
||||
? null
|
||||
: new CharsSpliterator(array, lo, index = mid, cs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEachRemaining(IntConsumer action) {
|
||||
byte[] a; int i, hi; // hoist accesses and checks from loop
|
||||
if (action == null)
|
||||
throw new NullPointerException();
|
||||
if ((a = array).length >= (hi = fence) &&
|
||||
(i = index) >= 0 && i < (index = hi)) {
|
||||
do { action.accept(a[i] & 0xff); } while (++i < hi);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tryAdvance(IntConsumer action) {
|
||||
if (action == null)
|
||||
throw new NullPointerException();
|
||||
if (index >= 0 && index < fence) {
|
||||
action.accept(array[index++] & 0xff);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long estimateSize() { return (long)(fence - index); }
|
||||
|
||||
@Override
|
||||
public int characteristics() {
|
||||
return cs;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
public static void getCharsSB(byte[] val, int srcBegin, int srcEnd, char dst[], int dstBegin) {
|
||||
checkOffset(srcEnd, val.length);
|
||||
getChars(val, srcBegin, srcEnd, dst, dstBegin);
|
||||
}
|
||||
|
||||
public static void inflateSB(byte[] val, byte[] dst, int dstOff, int count) {
|
||||
checkOffset(count, val.length);
|
||||
checkOffset(dstOff + count, dst.length >> 1); // dst is utf16
|
||||
inflate(val, 0, dst, dstOff, count);
|
||||
}
|
||||
}
|
971
jdk/src/java.base/share/classes/java/lang/StringUTF16.java
Normal file
971
jdk/src/java.base/share/classes/java/lang/StringUTF16.java
Normal file
@ -0,0 +1,971 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.lang;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
import java.util.Spliterator;
|
||||
import java.util.function.IntConsumer;
|
||||
import jdk.internal.HotSpotIntrinsicCandidate;
|
||||
|
||||
import static java.lang.String.UTF16;
|
||||
import static java.lang.String.LATIN1;
|
||||
import static java.lang.String.checkIndex;
|
||||
import static java.lang.String.checkOffset;
|
||||
|
||||
final class StringUTF16 {
|
||||
|
||||
public static byte[] newBytesFor(int len) {
|
||||
if (len < 0) {
|
||||
throw new NegativeArraySizeException();
|
||||
}
|
||||
if (len > MAX_LENGTH) {
|
||||
throw new OutOfMemoryError("UTF16 String size is " + len +
|
||||
", should be less than " + MAX_LENGTH);
|
||||
}
|
||||
return new byte[len << 1];
|
||||
}
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
public static void putChar(byte[] val, int index, int c) {
|
||||
index <<= 1;
|
||||
val[index++] = (byte)(c >> HI_BYTE_SHIFT);
|
||||
val[index] = (byte)(c >> LO_BYTE_SHIFT);
|
||||
}
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
public static char getChar(byte[] val, int index) {
|
||||
index <<= 1;
|
||||
return (char)(((val[index++] & 0xff) << HI_BYTE_SHIFT) |
|
||||
((val[index] & 0xff) << LO_BYTE_SHIFT));
|
||||
}
|
||||
|
||||
public static char charAt(byte[] value, int index) {
|
||||
if (index < 0 || index >= value.length >> 1) {
|
||||
throw new StringIndexOutOfBoundsException(index);
|
||||
}
|
||||
return getChar(value, index);
|
||||
}
|
||||
|
||||
public static int length(byte[] value) {
|
||||
return value.length >> 1;
|
||||
}
|
||||
|
||||
public static int codePointAt(byte[] value, int index, int end) {
|
||||
char c1 = getChar(value, index);
|
||||
if (Character.isHighSurrogate(c1) && ++index < end) {
|
||||
char c2 = getChar(value, index);
|
||||
if (Character.isLowSurrogate(c2)) {
|
||||
return Character.toCodePoint(c1, c2);
|
||||
}
|
||||
}
|
||||
return c1;
|
||||
}
|
||||
|
||||
public static int codePointBefore(byte[] value, int index) {
|
||||
char c2 = getChar(value, --index);
|
||||
if (Character.isLowSurrogate(c2) && index > 0) {
|
||||
char c1 = getChar(value, --index);
|
||||
if (Character.isHighSurrogate(c1)) {
|
||||
return Character.toCodePoint(c1, c2);
|
||||
}
|
||||
}
|
||||
return c2;
|
||||
}
|
||||
|
||||
public static int codePointCount(byte[] value, int beginIndex, int endIndex) {
|
||||
int count = endIndex - beginIndex;
|
||||
for (int i = beginIndex; i < endIndex; ) {
|
||||
if (Character.isHighSurrogate(getChar(value, i++)) &&
|
||||
i < endIndex &&
|
||||
Character.isLowSurrogate(getChar(value, i))) {
|
||||
count--;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
public static char[] toChars(byte[] value) {
|
||||
char[] dst = new char[value.length >> 1];
|
||||
getChars(value, 0, dst.length, dst, 0);
|
||||
return dst;
|
||||
}
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
public static byte[] toBytes(char[] value, int off, int len) {
|
||||
byte[] val = newBytesFor(len);
|
||||
for (int i = 0; i < len; i++) {
|
||||
putChar(val, i, value[off++]);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
public static byte[] compress(char[] val, int off, int len) {
|
||||
byte[] ret = new byte[len];
|
||||
if (compress(val, off, ret, 0, len) == len) {
|
||||
return ret;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static byte[] compress(byte[] val, int off, int len) {
|
||||
byte[] ret = new byte[len];
|
||||
if (compress(val, off, ret, 0, len) == len) {
|
||||
return ret;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// compressedCopy char[] -> byte[]
|
||||
@HotSpotIntrinsicCandidate
|
||||
private static int compress(char[] src, int srcOff, byte[] dst, int dstOff, int len) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
int c = src[srcOff++];
|
||||
if (c >>> 8 != 0) {
|
||||
return 0;
|
||||
}
|
||||
dst[dstOff++] = (byte)c;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
// compressedCopy byte[] -> byte[]
|
||||
@HotSpotIntrinsicCandidate
|
||||
public static int compress(byte[] src, int srcOff, byte[] dst, int dstOff, int len) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
int c = getChar(src, srcOff++);
|
||||
if (c >>> 8 != 0) {
|
||||
return 0;
|
||||
}
|
||||
dst[dstOff++] = (byte)c;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
public static byte[] toBytes(int[] val, int index, int len) {
|
||||
final int end = index + len;
|
||||
// Pass 1: Compute precise size of char[]
|
||||
int n = len;
|
||||
for (int i = index; i < end; i++) {
|
||||
int cp = val[i];
|
||||
if (Character.isBmpCodePoint(cp))
|
||||
continue;
|
||||
else if (Character.isValidCodePoint(cp))
|
||||
n++;
|
||||
else throw new IllegalArgumentException(Integer.toString(cp));
|
||||
}
|
||||
// Pass 2: Allocate and fill in <high, low> pair
|
||||
byte[] buf = newBytesFor(n);
|
||||
for (int i = index, j = 0; i < end; i++, j++) {
|
||||
int cp = val[i];
|
||||
if (Character.isBmpCodePoint(cp)) {
|
||||
putChar(buf, j, cp);
|
||||
} else {
|
||||
putChar(buf, j++, Character.highSurrogate(cp));
|
||||
putChar(buf, j, Character.lowSurrogate(cp));
|
||||
}
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
public static byte[] toBytes(char c) {
|
||||
byte[] result = new byte[2];
|
||||
putChar(result, 0, c);
|
||||
return result;
|
||||
}
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
public static void getChars(byte[] value, int srcBegin, int srcEnd, char dst[], int dstBegin) {
|
||||
for (int i = srcBegin; i < srcEnd; i++) {
|
||||
dst[dstBegin++] = getChar(value, i);
|
||||
}
|
||||
}
|
||||
|
||||
/* @see java.lang.String.getBytes(int, int, byte[], int) */
|
||||
public static void getBytes(byte[] value, int srcBegin, int srcEnd, byte dst[], int dstBegin) {
|
||||
srcBegin <<= 1;
|
||||
srcEnd <<= 1;
|
||||
for (int i = srcBegin + (1 >> LO_BYTE_SHIFT); i < srcEnd; i += 2) {
|
||||
dst[dstBegin++] = value[i];
|
||||
}
|
||||
}
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
public static boolean equals(byte[] value, byte[] other) {
|
||||
if (value.length == other.length) {
|
||||
int len = value.length >> 1;
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (getChar(value, i) != getChar(other, i)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
public static int compareTo(byte[] value, byte[] other) {
|
||||
int len1 = length(value);
|
||||
int len2 = length(other);
|
||||
int lim = Math.min(len1, len2);
|
||||
for (int k = 0; k < lim; k++) {
|
||||
char c1 = getChar(value, k);
|
||||
char c2 = getChar(other, k);
|
||||
if (c1 != c2) {
|
||||
return c1 - c2;
|
||||
}
|
||||
}
|
||||
return len1 - len2;
|
||||
}
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
public static int compareToLatin1(byte[] value, byte[] other) {
|
||||
int len1 = length(value);
|
||||
int len2 = StringLatin1.length(other);
|
||||
int lim = Math.min(len1, len2);
|
||||
for (int k = 0; k < lim; k++) {
|
||||
char c1 = getChar(value, k);
|
||||
char c2 = StringLatin1.getChar(other, k);
|
||||
if (c1 != c2) {
|
||||
return c1 - c2;
|
||||
}
|
||||
}
|
||||
return len1 - len2;
|
||||
}
|
||||
|
||||
public static int hashCode(byte[] value) {
|
||||
int h = 0;
|
||||
int length = value.length >> 1;
|
||||
for (int i = 0; i < length; i++) {
|
||||
h = 31 * h + getChar(value, i);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
public static int indexOf(byte[] value, int ch, int fromIndex) {
|
||||
int max = value.length >> 1;
|
||||
if (fromIndex < 0) {
|
||||
fromIndex = 0;
|
||||
} else if (fromIndex >= max) {
|
||||
// Note: fromIndex might be near -1>>>1.
|
||||
return -1;
|
||||
}
|
||||
if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
|
||||
// handle most cases here (ch is a BMP code point or a
|
||||
// negative value (invalid code point))
|
||||
return indexOfChar(value, ch, fromIndex, max);
|
||||
} else {
|
||||
return indexOfSupplementary(value, ch, fromIndex, max);
|
||||
}
|
||||
}
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
public static int indexOf(byte[] value, byte[] str) {
|
||||
if (str.length == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (value.length == 0) {
|
||||
return -1;
|
||||
}
|
||||
return indexOf(value, length(value), str, length(str), 0);
|
||||
}
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
public static int indexOf(byte[] value, int valueCount, byte[] str, int strCount, int fromIndex) {
|
||||
char first = getChar(str, 0);
|
||||
int max = (valueCount - strCount);
|
||||
for (int i = fromIndex; i <= max; i++) {
|
||||
// Look for first character.
|
||||
if (getChar(value, i) != first) {
|
||||
while (++i <= max && getChar(value, i) != first);
|
||||
}
|
||||
// Found first character, now look at the rest of value
|
||||
if (i <= max) {
|
||||
int j = i + 1;
|
||||
int end = j + strCount - 1;
|
||||
for (int k = 1; j < end && getChar(value, j) == getChar(str, k); j++, k++);
|
||||
if (j == end) {
|
||||
// Found whole string.
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles indexOf Latin1 substring in UTF16 string.
|
||||
*/
|
||||
@HotSpotIntrinsicCandidate
|
||||
public static int indexOfLatin1(byte[] value, byte[] str) {
|
||||
if (str.length == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (value.length == 0) {
|
||||
return -1;
|
||||
}
|
||||
return indexOfLatin1(value, length(value), str, str.length, 0);
|
||||
}
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
public static int indexOfLatin1(byte[] src, int srcCount, byte[] tgt, int tgtCount, int fromIndex) {
|
||||
char first = (char)(tgt[0] & 0xff);
|
||||
int max = (srcCount - tgtCount);
|
||||
for (int i = fromIndex; i <= max; i++) {
|
||||
// Look for first character.
|
||||
if (getChar(src, i) != first) {
|
||||
while (++i <= max && getChar(src, i) != first);
|
||||
}
|
||||
// Found first character, now look at the rest of v2
|
||||
if (i <= max) {
|
||||
int j = i + 1;
|
||||
int end = j + tgtCount - 1;
|
||||
for (int k = 1;
|
||||
j < end && getChar(src, j) == (tgt[k] & 0xff);
|
||||
j++, k++);
|
||||
if (j == end) {
|
||||
// Found whole string.
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
private static int indexOfChar(byte[] value, int ch, int fromIndex, int max) {
|
||||
for (int i = fromIndex; i < max; i++) {
|
||||
if (getChar(value, i) == ch) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles (rare) calls of indexOf with a supplementary character.
|
||||
*/
|
||||
private static int indexOfSupplementary(byte[] value, int ch, int fromIndex, int max) {
|
||||
if (Character.isValidCodePoint(ch)) {
|
||||
final char hi = Character.highSurrogate(ch);
|
||||
final char lo = Character.lowSurrogate(ch);
|
||||
for (int i = fromIndex; i < max - 1; i++) {
|
||||
if (getChar(value, i) == hi && getChar(value, i + 1 ) == lo) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static int lastIndexOf(byte[] src, int srcCount,
|
||||
byte[] tgt, int tgtCount, int fromIndex) {
|
||||
int min = tgtCount - 1;
|
||||
int i = min + fromIndex;
|
||||
int strLastIndex = tgtCount - 1;
|
||||
char strLastChar = getChar(tgt, strLastIndex);
|
||||
|
||||
startSearchForLastChar:
|
||||
while (true) {
|
||||
while (i >= min && getChar(src, i) != strLastChar) {
|
||||
i--;
|
||||
}
|
||||
if (i < min) {
|
||||
return -1;
|
||||
}
|
||||
int j = i - 1;
|
||||
int start = j - strLastIndex;
|
||||
int k = strLastIndex - 1;
|
||||
while (j > start) {
|
||||
if (getChar(src, j--) != getChar(tgt, k--)) {
|
||||
i--;
|
||||
continue startSearchForLastChar;
|
||||
}
|
||||
}
|
||||
return start + 1;
|
||||
}
|
||||
}
|
||||
|
||||
public static int lastIndexOf(byte[] value, int ch, int fromIndex) {
|
||||
if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
|
||||
// handle most cases here (ch is a BMP code point or a
|
||||
// negative value (invalid code point))
|
||||
int i = Math.min(fromIndex, (value.length >> 1) - 1);
|
||||
for (; i >= 0; i--) {
|
||||
if (getChar(value, i) == ch) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
} else {
|
||||
return lastIndexOfSupplementary(value, ch, fromIndex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles (rare) calls of lastIndexOf with a supplementary character.
|
||||
*/
|
||||
private static int lastIndexOfSupplementary(final byte[] value, int ch, int fromIndex) {
|
||||
if (Character.isValidCodePoint(ch)) {
|
||||
char hi = Character.highSurrogate(ch);
|
||||
char lo = Character.lowSurrogate(ch);
|
||||
int i = Math.min(fromIndex, (value.length >> 1) - 2);
|
||||
for (; i >= 0; i--) {
|
||||
if (getChar(value, i) == hi && getChar(value, i + 1) == lo) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static String replace(byte[] value, char oldChar, char newChar) {
|
||||
int len = value.length >> 1;
|
||||
int i = -1;
|
||||
while (++i < len) {
|
||||
if (getChar(value, i) == oldChar) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < len) {
|
||||
byte buf[] = new byte[value.length];
|
||||
for (int j = 0; j < i; j++) {
|
||||
putChar(buf, j, getChar(value, j)); // TBD:arraycopy?
|
||||
}
|
||||
while (i < len) {
|
||||
char c = getChar(value, i);
|
||||
putChar(buf, i, c == oldChar ? newChar : c);
|
||||
i++;
|
||||
}
|
||||
// Check if we should try to compress to latin1
|
||||
if (String.COMPACT_STRINGS &&
|
||||
!StringLatin1.canEncode(oldChar) &&
|
||||
StringLatin1.canEncode(newChar)) {
|
||||
byte[] val = compress(buf, 0, len);
|
||||
if (val != null) {
|
||||
return new String(val, LATIN1);
|
||||
}
|
||||
}
|
||||
return new String(buf, UTF16);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean regionMatchesCI(byte[] value, int toffset,
|
||||
byte[] other, int ooffset, int len) {
|
||||
int last = toffset + len;
|
||||
while (toffset < last) {
|
||||
char c1 = getChar(value, toffset++);
|
||||
char c2 = getChar(other, ooffset++);
|
||||
if (c1 == c2) {
|
||||
continue;
|
||||
}
|
||||
// try converting both characters to uppercase.
|
||||
// If the results match, then the comparison scan should
|
||||
// continue.
|
||||
char u1 = Character.toUpperCase(c1);
|
||||
char u2 = Character.toUpperCase(c2);
|
||||
if (u1 == u2) {
|
||||
continue;
|
||||
}
|
||||
// Unfortunately, conversion to uppercase does not work properly
|
||||
// for the Georgian alphabet, which has strange rules about case
|
||||
// conversion. So we need to make one last check before
|
||||
// exiting.
|
||||
if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean regionMatchesCI_Latin1(byte[] value, int toffset,
|
||||
byte[] other, int ooffset,
|
||||
int len) {
|
||||
int last = toffset + len;
|
||||
while (toffset < last) {
|
||||
char c1 = getChar(value, toffset++);
|
||||
char c2 = (char)(other[ooffset++] & 0xff);
|
||||
if (c1 == c2) {
|
||||
continue;
|
||||
}
|
||||
char u1 = Character.toUpperCase(c1);
|
||||
char u2 = Character.toUpperCase(c2);
|
||||
if (u1 == u2) {
|
||||
continue;
|
||||
}
|
||||
if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static String toLowerCase(String str, byte[] value, Locale locale) {
|
||||
if (locale == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
int first;
|
||||
boolean hasSurr = false;
|
||||
final int len = value.length >> 1;
|
||||
|
||||
// Now check if there are any characters that need to be changed, or are surrogate
|
||||
for (first = 0 ; first < len; first++) {
|
||||
int cp = (int)getChar(value, first);
|
||||
if (Character.isSurrogate((char)cp)) {
|
||||
hasSurr = true;
|
||||
break;
|
||||
}
|
||||
if (cp != Character.toLowerCase(cp)) { // no need to check Character.ERROR
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (first == len)
|
||||
return str;
|
||||
byte[] result = new byte[value.length];
|
||||
System.arraycopy(value, 0, result, 0, first << 1); // Just copy the first few
|
||||
// lowerCase characters.
|
||||
String lang = locale.getLanguage();
|
||||
if (lang == "tr" || lang == "az" || lang == "lt") {
|
||||
return toLowerCaseEx(str, value, result, first, locale, true);
|
||||
}
|
||||
if (hasSurr) {
|
||||
return toLowerCaseEx(str, value, result, first, locale, false);
|
||||
}
|
||||
int bits = 0;
|
||||
for (int i = first; i < len; i++) {
|
||||
int cp = (int)getChar(value, i);
|
||||
if (cp == '\u03A3' || // GREEK CAPITAL LETTER SIGMA
|
||||
Character.isSurrogate((char)cp)) {
|
||||
return toLowerCaseEx(str, value, result, i, locale, false);
|
||||
}
|
||||
if (cp == '\u0130') { // LATIN CAPITAL LETTER I WITH DOT ABOVE
|
||||
return toLowerCaseEx(str, value, result, i, locale, true);
|
||||
}
|
||||
cp = Character.toLowerCase(cp);
|
||||
if (!Character.isBmpCodePoint(cp)) {
|
||||
return toLowerCaseEx(str, value, result, i, locale, false);
|
||||
}
|
||||
bits |= cp;
|
||||
putChar(result, i, cp);
|
||||
}
|
||||
if (bits >>> 8 != 0) {
|
||||
return new String(result, UTF16);
|
||||
} else {
|
||||
return newString(result, 0, len);
|
||||
}
|
||||
}
|
||||
|
||||
private static String toLowerCaseEx(String str, byte[] value,
|
||||
byte[] result, int first, Locale locale,
|
||||
boolean localeDependent) {
|
||||
int resultOffset = first;
|
||||
int length = value.length >> 1;
|
||||
int srcCount;
|
||||
for (int i = first; i < length; i += srcCount) {
|
||||
int srcChar = getChar(value, i);
|
||||
int lowerChar;
|
||||
char[] lowerCharArray;
|
||||
srcCount = 1;
|
||||
if (Character.isSurrogate((char)srcChar)) {
|
||||
srcChar = codePointAt(value, i, length);
|
||||
srcCount = Character.charCount(srcChar);
|
||||
}
|
||||
if (localeDependent ||
|
||||
srcChar == '\u03A3' || // GREEK CAPITAL LETTER SIGMA
|
||||
srcChar == '\u0130') { // LATIN CAPITAL LETTER I WITH DOT ABOVE
|
||||
lowerChar = ConditionalSpecialCasing.toLowerCaseEx(str, i, locale);
|
||||
} else {
|
||||
lowerChar = Character.toLowerCase(srcChar);
|
||||
}
|
||||
if (Character.isBmpCodePoint(lowerChar)) { // Character.ERROR is not a bmp
|
||||
putChar(result, resultOffset++, lowerChar);
|
||||
} else {
|
||||
if (lowerChar == Character.ERROR) {
|
||||
lowerCharArray = ConditionalSpecialCasing.toLowerCaseCharArray(str, i, locale);
|
||||
} else {
|
||||
lowerCharArray = Character.toChars(lowerChar);
|
||||
}
|
||||
/* Grow result if needed */
|
||||
int mapLen = lowerCharArray.length;
|
||||
if (mapLen > srcCount) {
|
||||
byte[] result2 = newBytesFor((result.length >> 1) + mapLen - srcCount);
|
||||
System.arraycopy(result, 0, result2, 0, resultOffset << 1);
|
||||
result = result2;
|
||||
}
|
||||
for (int x = 0; x < mapLen; ++x) {
|
||||
putChar(result, resultOffset++, lowerCharArray[x]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return newString(result, 0, resultOffset);
|
||||
}
|
||||
|
||||
public static String toUpperCase(String str, byte[] value, Locale locale) {
|
||||
if (locale == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
int first;
|
||||
boolean hasSurr = false;
|
||||
final int len = value.length >> 1;
|
||||
|
||||
// Now check if there are any characters that need to be changed, or are surrogate
|
||||
for (first = 0 ; first < len; first++) {
|
||||
int cp = (int)getChar(value, first);
|
||||
if (Character.isSurrogate((char)cp)) {
|
||||
hasSurr = true;
|
||||
break;
|
||||
}
|
||||
if (cp != Character.toUpperCaseEx(cp)) { // no need to check Character.ERROR
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (first == len) {
|
||||
return str;
|
||||
}
|
||||
byte[] result = new byte[value.length];
|
||||
System.arraycopy(value, 0, result, 0, first << 1); // Just copy the first few
|
||||
// upperCase characters.
|
||||
String lang = locale.getLanguage();
|
||||
if (lang == "tr" || lang == "az" || lang == "lt") {
|
||||
return toUpperCaseEx(str, value, result, first, locale, true);
|
||||
}
|
||||
if (hasSurr) {
|
||||
return toUpperCaseEx(str, value, result, first, locale, false);
|
||||
}
|
||||
int bits = 0;
|
||||
for (int i = first; i < len; i++) {
|
||||
int cp = (int)getChar(value, i);
|
||||
if (Character.isSurrogate((char)cp)) {
|
||||
return toUpperCaseEx(str, value, result, i, locale, false);
|
||||
}
|
||||
cp = Character.toUpperCaseEx(cp);
|
||||
if (!Character.isBmpCodePoint(cp)) { // Character.ERROR is not bmp
|
||||
return toUpperCaseEx(str, value, result, i, locale, false);
|
||||
}
|
||||
bits |= cp;
|
||||
putChar(result, i, cp);
|
||||
}
|
||||
if (bits >>> 8 != 0) {
|
||||
return new String(result, UTF16);
|
||||
} else {
|
||||
return newString(result, 0, len);
|
||||
}
|
||||
}
|
||||
|
||||
private static String toUpperCaseEx(String str, byte[] value,
|
||||
byte[] result, int first,
|
||||
Locale locale, boolean localeDependent)
|
||||
{
|
||||
int resultOffset = first;
|
||||
int length = value.length >> 1;
|
||||
int srcCount;
|
||||
for (int i = first; i < length; i += srcCount) {
|
||||
int srcChar = getChar(value, i);
|
||||
int upperChar;
|
||||
char[] upperCharArray;
|
||||
srcCount = 1;
|
||||
if (Character.isSurrogate((char)srcChar)) {
|
||||
srcChar = codePointAt(value, i, length);
|
||||
srcCount = Character.charCount(srcChar);
|
||||
}
|
||||
if (localeDependent) {
|
||||
upperChar = ConditionalSpecialCasing.toUpperCaseEx(str, i, locale);
|
||||
} else {
|
||||
upperChar = Character.toUpperCaseEx(srcChar);
|
||||
}
|
||||
if (Character.isBmpCodePoint(upperChar)) {
|
||||
putChar(result, resultOffset++, upperChar);
|
||||
} else {
|
||||
if (upperChar == Character.ERROR) {
|
||||
if (localeDependent) {
|
||||
upperCharArray =
|
||||
ConditionalSpecialCasing.toUpperCaseCharArray(str, i, locale);
|
||||
} else {
|
||||
upperCharArray = Character.toUpperCaseCharArray(srcChar);
|
||||
}
|
||||
} else {
|
||||
upperCharArray = Character.toChars(upperChar);
|
||||
}
|
||||
/* Grow result if needed */
|
||||
int mapLen = upperCharArray.length;
|
||||
if (mapLen > srcCount) {
|
||||
byte[] result2 = newBytesFor((result.length >> 1) + mapLen - srcCount);
|
||||
System.arraycopy(result, 0, result2, 0, resultOffset << 1);
|
||||
result = result2;
|
||||
}
|
||||
for (int x = 0; x < mapLen; ++x) {
|
||||
putChar(result, resultOffset++, upperCharArray[x]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return newString(result, 0, resultOffset);
|
||||
}
|
||||
|
||||
public static String trim(byte[] value) {
|
||||
int length = value.length >> 1;
|
||||
int len = length;
|
||||
int st = 0;
|
||||
while (st < len && getChar(value, st) <= ' ') {
|
||||
st++;
|
||||
}
|
||||
while (st < len && getChar(value, len - 1) <= ' ') {
|
||||
len--;
|
||||
}
|
||||
return ((st > 0) || (len < length )) ?
|
||||
new String(Arrays.copyOfRange(value, st << 1, len << 1), UTF16) :
|
||||
null;
|
||||
}
|
||||
|
||||
public static void putChars(byte[] val, int index, char[] str, int off, int end) {
|
||||
while (off < end) {
|
||||
putChar(val, index++, str[off++]);
|
||||
}
|
||||
}
|
||||
|
||||
public static String newString(byte[] val, int index, int len) {
|
||||
if (String.COMPACT_STRINGS) {
|
||||
byte[] buf = compress(val, index, len);
|
||||
if (buf != null) {
|
||||
return new String(buf, LATIN1);
|
||||
}
|
||||
}
|
||||
int last = index + len;
|
||||
return new String(Arrays.copyOfRange(val, index << 1, last << 1), UTF16);
|
||||
}
|
||||
|
||||
public static void fillNull(byte[] val, int index, int end) {
|
||||
Arrays.fill(val, index << 1, end << 1, (byte)0);
|
||||
}
|
||||
|
||||
static class CharsSpliterator implements Spliterator.OfInt {
|
||||
private final byte[] array;
|
||||
private int index; // current index, modified on advance/split
|
||||
private final int fence; // one past last index
|
||||
private final int cs;
|
||||
|
||||
CharsSpliterator(byte[] array, int acs) {
|
||||
this(array, 0, array.length >> 1, acs);
|
||||
}
|
||||
|
||||
CharsSpliterator(byte[] array, int origin, int fence, int acs) {
|
||||
this.array = array;
|
||||
this.index = origin;
|
||||
this.fence = fence;
|
||||
this.cs = acs | Spliterator.ORDERED | Spliterator.SIZED
|
||||
| Spliterator.SUBSIZED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OfInt trySplit() {
|
||||
int lo = index, mid = (lo + fence) >>> 1;
|
||||
return (lo >= mid)
|
||||
? null
|
||||
: new CharsSpliterator(array, lo, index = mid, cs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEachRemaining(IntConsumer action) {
|
||||
byte[] a; int i, hi; // hoist accesses and checks from loop
|
||||
if (action == null)
|
||||
throw new NullPointerException();
|
||||
if (((a = array).length >> 1) >= (hi = fence) &&
|
||||
(i = index) >= 0 && i < (index = hi)) {
|
||||
do { action.accept(getChar(a, i)); } while (++i < hi);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tryAdvance(IntConsumer action) {
|
||||
if (action == null)
|
||||
throw new NullPointerException();
|
||||
if (index >= 0 && index < fence) {
|
||||
action.accept(getChar(array, index++));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long estimateSize() { return (long)(fence - index); }
|
||||
|
||||
@Override
|
||||
public int characteristics() {
|
||||
return cs;
|
||||
}
|
||||
}
|
||||
|
||||
static class CodePointsSpliterator implements Spliterator.OfInt {
|
||||
private final byte[] array;
|
||||
private int index; // current index, modified on advance/split
|
||||
private final int fence; // one past last index
|
||||
private final int cs;
|
||||
|
||||
CodePointsSpliterator(byte[] array, int acs) {
|
||||
this(array, 0, array.length >> 1, acs);
|
||||
}
|
||||
|
||||
CodePointsSpliterator(byte[] array, int origin, int fence, int acs) {
|
||||
this.array = array;
|
||||
this.index = origin;
|
||||
this.fence = fence;
|
||||
this.cs = acs | Spliterator.ORDERED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OfInt trySplit() {
|
||||
int lo = index, mid = (lo + fence) >>> 1;
|
||||
if (lo >= mid)
|
||||
return null;
|
||||
|
||||
int midOneLess;
|
||||
// If the mid-point intersects a surrogate pair
|
||||
if (Character.isLowSurrogate(getChar(array, mid)) &&
|
||||
Character.isHighSurrogate(getChar(array, midOneLess = (mid -1)))) {
|
||||
// If there is only one pair it cannot be split
|
||||
if (lo >= midOneLess)
|
||||
return null;
|
||||
// Shift the mid-point to align with the surrogate pair
|
||||
return new CodePointsSpliterator(array, lo, index = midOneLess, cs);
|
||||
}
|
||||
return new CodePointsSpliterator(array, lo, index = mid, cs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEachRemaining(IntConsumer action) {
|
||||
byte[] a; int i, hi; // hoist accesses and checks from loop
|
||||
if (action == null)
|
||||
throw new NullPointerException();
|
||||
if (((a = array).length >> 1) >= (hi = fence) &&
|
||||
(i = index) >= 0 && i < (index = hi)) {
|
||||
do {
|
||||
i = advance(a, i, hi, action);
|
||||
} while (i < hi);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tryAdvance(IntConsumer action) {
|
||||
if (action == null)
|
||||
throw new NullPointerException();
|
||||
if (index >= 0 && index < fence) {
|
||||
index = advance(array, index, fence, action);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Advance one code point from the index, i, and return the next
|
||||
// index to advance from
|
||||
private static int advance(byte[] a, int i, int hi, IntConsumer action) {
|
||||
char c1 = getChar(a, i++);
|
||||
int cp = c1;
|
||||
if (Character.isHighSurrogate(c1) && i < hi) {
|
||||
char c2 = getChar(a, i);
|
||||
if (Character.isLowSurrogate(c2)) {
|
||||
i++;
|
||||
cp = Character.toCodePoint(c1, c2);
|
||||
}
|
||||
}
|
||||
action.accept(cp);
|
||||
return i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long estimateSize() { return (long)(fence - index); }
|
||||
|
||||
@Override
|
||||
public int characteristics() {
|
||||
return cs;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
public static void getCharsSB(byte[] val, int srcBegin, int srcEnd, char dst[], int dstBegin) {
|
||||
checkOffset(srcEnd, val.length >> 1);
|
||||
getChars(val, srcBegin, srcEnd, dst, dstBegin);
|
||||
}
|
||||
|
||||
public static void putCharSB(byte[] val, int index, int c) {
|
||||
checkIndex(index, val.length >> 1);
|
||||
putChar(val, index, c);
|
||||
}
|
||||
|
||||
public static void putCharsSB(byte[] val, int index, char[] ca, int off, int end) {
|
||||
checkOffset(index + end - off, val.length >> 1);
|
||||
putChars(val, index, ca, off, end);
|
||||
}
|
||||
|
||||
public static void putCharsSB(byte[] val, int index, CharSequence s, int off, int end) {
|
||||
checkOffset(index + end - off, val.length >> 1);
|
||||
for (int i = off; i < end; i++) {
|
||||
putChar(val, index++, s.charAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
public static int codePointAtSB(byte[] val, int index, int end) {
|
||||
checkOffset(end, val.length >> 1);
|
||||
return codePointAt(val, index, end);
|
||||
}
|
||||
|
||||
public static int codePointBeforeSB(byte[] val, int index) {
|
||||
checkOffset(index, val.length >> 1);
|
||||
return codePointBefore(val, index);
|
||||
}
|
||||
|
||||
public static int codePointCountSB(byte[] val, int beginIndex, int endIndex) {
|
||||
checkOffset(endIndex, val.length >> 1);
|
||||
return codePointCount(val, beginIndex, endIndex);
|
||||
}
|
||||
|
||||
public static String newStringSB(byte[] val, int index, int len) {
|
||||
checkOffset(index + len, val.length >> 1);
|
||||
return newString(val, index, len);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
private static native boolean isBigEndian();
|
||||
|
||||
static final int HI_BYTE_SHIFT;
|
||||
static final int LO_BYTE_SHIFT;
|
||||
static {
|
||||
if (isBigEndian()) {
|
||||
HI_BYTE_SHIFT = 8;
|
||||
LO_BYTE_SHIFT = 0;
|
||||
} else {
|
||||
HI_BYTE_SHIFT = 0;
|
||||
LO_BYTE_SHIFT = 8;
|
||||
}
|
||||
}
|
||||
|
||||
static final int MAX_LENGTH = Integer.MAX_VALUE >> 1;
|
||||
}
|
@ -2685,6 +2685,7 @@ public class Arrays {
|
||||
* @param a2 the other array to be tested for equality
|
||||
* @return {@code true} if the two arrays are equal
|
||||
*/
|
||||
@HotSpotIntrinsicCandidate
|
||||
public static boolean equals(byte[] a, byte[] a2) {
|
||||
if (a==a2)
|
||||
return true;
|
||||
|
@ -32,4 +32,8 @@ package sun.nio.cs;
|
||||
|
||||
public interface ArrayDecoder {
|
||||
int decode(byte[] src, int off, int len, char[] dst);
|
||||
|
||||
default boolean isASCIICompatible() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -26,10 +26,24 @@
|
||||
package sun.nio.cs;
|
||||
|
||||
/*
|
||||
* FastPath char[]->byte[] encoder, REPLACE on malformed input or
|
||||
* FastPath char[]/byte[] -> byte[] encoder, REPLACE on malformed input or
|
||||
* unmappable input.
|
||||
*/
|
||||
|
||||
public interface ArrayEncoder {
|
||||
|
||||
// is only used by j.u.zip.ZipCoder for utf8
|
||||
int encode(char[] src, int off, int len, byte[] dst);
|
||||
|
||||
default int encodeFromLatin1(byte[] src, int sp, int len, byte[] dst) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
default int encodeFromUTF16(byte[] src, int sp, int len, byte[] dst) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
default boolean isASCIICompatible() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -115,6 +115,7 @@ public class DoubleByte {
|
||||
final char[] b2cSB;
|
||||
final int b2Min;
|
||||
final int b2Max;
|
||||
final boolean isASCIICompatible;
|
||||
|
||||
// for SimpleEUC override
|
||||
protected CoderResult crMalformedOrUnderFlow(int b) {
|
||||
@ -132,16 +133,23 @@ public class DoubleByte {
|
||||
|
||||
public Decoder(Charset cs, float avgcpb, float maxcpb,
|
||||
char[][] b2c, char[] b2cSB,
|
||||
int b2Min, int b2Max) {
|
||||
int b2Min, int b2Max,
|
||||
boolean isASCIICompatible) {
|
||||
super(cs, avgcpb, maxcpb);
|
||||
this.b2c = b2c;
|
||||
this.b2cSB = b2cSB;
|
||||
this.b2Min = b2Min;
|
||||
this.b2Max = b2Max;
|
||||
this.isASCIICompatible = isASCIICompatible;
|
||||
}
|
||||
|
||||
public Decoder(Charset cs, char[][] b2c, char[] b2cSB, int b2Min, int b2Max,
|
||||
boolean isASCIICompatible) {
|
||||
this(cs, 0.5f, 1.0f, b2c, b2cSB, b2Min, b2Max, isASCIICompatible);
|
||||
}
|
||||
|
||||
public Decoder(Charset cs, char[][] b2c, char[] b2cSB, int b2Min, int b2Max) {
|
||||
this(cs, 0.5f, 1.0f, b2c, b2cSB, b2Min, b2Max);
|
||||
this(cs, 0.5f, 1.0f, b2c, b2cSB, b2Min, b2Max, false);
|
||||
}
|
||||
|
||||
protected CoderResult decodeArrayLoop(ByteBuffer src, CharBuffer dst) {
|
||||
@ -215,6 +223,7 @@ public class DoubleByte {
|
||||
return decodeBufferLoop(src, dst);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int decode(byte[] src, int sp, int len, char[] dst) {
|
||||
int dp = 0;
|
||||
int sl = sp + len;
|
||||
@ -230,12 +239,12 @@ public class DoubleByte {
|
||||
if (b2c[b1] == B2C_UNMAPPABLE || // isNotLeadingByte
|
||||
b2c[b2] != B2C_UNMAPPABLE || // isLeadingByte
|
||||
decodeSingle(b2) != UNMAPPABLE_DECODING) {
|
||||
sp--;
|
||||
sp--;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (c == UNMAPPABLE_DECODING) {
|
||||
c = repl;
|
||||
c = repl;
|
||||
}
|
||||
}
|
||||
dst[dp++] = c;
|
||||
@ -243,6 +252,11 @@ public class DoubleByte {
|
||||
return dp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isASCIICompatible() {
|
||||
return isASCIICompatible;
|
||||
}
|
||||
|
||||
public void implReset() {
|
||||
super.implReset();
|
||||
}
|
||||
@ -274,8 +288,14 @@ public class DoubleByte {
|
||||
private int currentState;
|
||||
|
||||
public Decoder_EBCDIC(Charset cs,
|
||||
char[][] b2c, char[] b2cSB, int b2Min, int b2Max) {
|
||||
super(cs, b2c, b2cSB, b2Min, b2Max);
|
||||
char[][] b2c, char[] b2cSB, int b2Min, int b2Max,
|
||||
boolean isASCIICompatible) {
|
||||
super(cs, b2c, b2cSB, b2Min, b2Max, isASCIICompatible);
|
||||
}
|
||||
|
||||
public Decoder_EBCDIC(Charset cs,
|
||||
char[][] b2c, char[] b2cSB, int b2Min, int b2Max) {
|
||||
super(cs, b2c, b2cSB, b2Min, b2Max, false);
|
||||
}
|
||||
|
||||
public void implReset() {
|
||||
@ -403,6 +423,7 @@ public class DoubleByte {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int decode(byte[] src, int sp, int len, char[] dst) {
|
||||
int dp = 0;
|
||||
int sl = sp + len;
|
||||
@ -451,8 +472,13 @@ public class DoubleByte {
|
||||
b2cSB_UNMAPPABLE = new char[0x100];
|
||||
Arrays.fill(b2cSB_UNMAPPABLE, UNMAPPABLE_DECODING);
|
||||
}
|
||||
public Decoder_DBCSONLY(Charset cs, char[][] b2c, char[] b2cSB, int b2Min, int b2Max,
|
||||
boolean isASCIICompatible) {
|
||||
super(cs, 0.5f, 1.0f, b2c, b2cSB_UNMAPPABLE, b2Min, b2Max, isASCIICompatible);
|
||||
}
|
||||
|
||||
public Decoder_DBCSONLY(Charset cs, char[][] b2c, char[] b2cSB, int b2Min, int b2Max) {
|
||||
super(cs, 0.5f, 1.0f, b2c, b2cSB_UNMAPPABLE, b2Min, b2Max);
|
||||
super(cs, 0.5f, 1.0f, b2c, b2cSB_UNMAPPABLE, b2Min, b2Max, false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -464,8 +490,9 @@ public class DoubleByte {
|
||||
private final int SS3 = 0x8F;
|
||||
|
||||
public Decoder_EUC_SIM(Charset cs,
|
||||
char[][] b2c, char[] b2cSB, int b2Min, int b2Max) {
|
||||
super(cs, b2c, b2cSB, b2Min, b2Max);
|
||||
char[][] b2c, char[] b2cSB, int b2Min, int b2Max,
|
||||
boolean isASCIICompatible) {
|
||||
super(cs, b2c, b2cSB, b2Min, b2Max, isASCIICompatible);
|
||||
}
|
||||
|
||||
// No support provided for G2/G3 for SimpleEUC
|
||||
@ -481,6 +508,7 @@ public class DoubleByte {
|
||||
return CoderResult.unmappableForLength(2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int decode(byte[] src, int sp, int len, char[] dst) {
|
||||
int dp = 0;
|
||||
int sl = sp + len;
|
||||
@ -515,17 +543,25 @@ public class DoubleByte {
|
||||
private final char[] c2b;
|
||||
private final char[] c2bIndex;
|
||||
protected Surrogate.Parser sgp;
|
||||
final boolean isASCIICompatible;
|
||||
|
||||
public Encoder(Charset cs, char[] c2b, char[] c2bIndex) {
|
||||
this(cs, c2b, c2bIndex, false);
|
||||
}
|
||||
|
||||
public Encoder(Charset cs, char[] c2b, char[] c2bIndex, boolean isASCIICompatible) {
|
||||
super(cs, 2.0f, 2.0f);
|
||||
this.c2b = c2b;
|
||||
this.c2bIndex = c2bIndex;
|
||||
this.isASCIICompatible = isASCIICompatible;
|
||||
}
|
||||
|
||||
public Encoder(Charset cs, float avg, float max, byte[] repl, char[] c2b, char[] c2bIndex) {
|
||||
public Encoder(Charset cs, float avg, float max, byte[] repl, char[] c2b, char[] c2bIndex,
|
||||
boolean isASCIICompatible) {
|
||||
super(cs, avg, max, repl);
|
||||
this.c2b = c2b;
|
||||
this.c2bIndex = c2bIndex;
|
||||
this.isASCIICompatible = isASCIICompatible;
|
||||
}
|
||||
|
||||
public boolean canEncode(char c) {
|
||||
@ -624,6 +660,7 @@ public class DoubleByte {
|
||||
repl = newReplacement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int encode(char[] src, int sp, int len, byte[] dst) {
|
||||
int dp = 0;
|
||||
int sl = sp + len;
|
||||
@ -647,11 +684,69 @@ public class DoubleByte {
|
||||
} else { // SingleByte
|
||||
dst[dp++] = (byte)bb;
|
||||
}
|
||||
}
|
||||
return dp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int encodeFromLatin1(byte[] src, int sp, int len, byte[] dst) {
|
||||
int dp = 0;
|
||||
int sl = sp + len;
|
||||
while (sp < sl) {
|
||||
char c = (char)(src[sp++] & 0xff);
|
||||
int bb = encodeChar(c);
|
||||
if (bb == UNMAPPABLE_ENCODING) {
|
||||
// no surrogate pair in latin1 string
|
||||
dst[dp++] = repl[0];
|
||||
if (repl.length > 1) {
|
||||
dst[dp++] = repl[1];
|
||||
}
|
||||
continue;
|
||||
} //else
|
||||
if (bb > MAX_SINGLEBYTE) { // DoubleByte
|
||||
dst[dp++] = (byte)(bb >> 8);
|
||||
dst[dp++] = (byte)bb;
|
||||
} else { // SingleByte
|
||||
dst[dp++] = (byte)bb;
|
||||
}
|
||||
|
||||
}
|
||||
return dp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int encodeFromUTF16(byte[] src, int sp, int len, byte[] dst) {
|
||||
int dp = 0;
|
||||
int sl = sp + len;
|
||||
while (sp < sl) {
|
||||
char c = StringUTF16.getChar(src, sp++);
|
||||
int bb = encodeChar(c);
|
||||
if (bb == UNMAPPABLE_ENCODING) {
|
||||
if (Character.isHighSurrogate(c) && sp < sl &&
|
||||
Character.isLowSurrogate(StringUTF16.getChar(src, sp))) {
|
||||
sp++;
|
||||
}
|
||||
dst[dp++] = repl[0];
|
||||
if (repl.length > 1) {
|
||||
dst[dp++] = repl[1];
|
||||
}
|
||||
continue;
|
||||
} //else
|
||||
if (bb > MAX_SINGLEBYTE) { // DoubleByte
|
||||
dst[dp++] = (byte)(bb >> 8);
|
||||
dst[dp++] = (byte)bb;
|
||||
} else { // SingleByte
|
||||
dst[dp++] = (byte)bb;
|
||||
}
|
||||
}
|
||||
return dp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isASCIICompatible() {
|
||||
return isASCIICompatible;
|
||||
}
|
||||
|
||||
public int encodeChar(char ch) {
|
||||
return c2b[c2bIndex[ch >> 8] + (ch & 0xff)];
|
||||
}
|
||||
@ -741,9 +836,11 @@ public class DoubleByte {
|
||||
}
|
||||
|
||||
public static class Encoder_DBCSONLY extends Encoder {
|
||||
|
||||
public Encoder_DBCSONLY(Charset cs, byte[] repl,
|
||||
char[] c2b, char[] c2bIndex) {
|
||||
super(cs, 2.0f, 2.0f, repl, c2b, c2bIndex);
|
||||
char[] c2b, char[] c2bIndex,
|
||||
boolean isASCIICompatible) {
|
||||
super(cs, 2.0f, 2.0f, repl, c2b, c2bIndex, isASCIICompatible);
|
||||
}
|
||||
|
||||
public int encodeChar(char ch) {
|
||||
@ -754,8 +851,6 @@ public class DoubleByte {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static class Encoder_EBCDIC extends Encoder {
|
||||
static final int SBCS = 0;
|
||||
static final int DBCS = 1;
|
||||
@ -764,8 +859,9 @@ public class DoubleByte {
|
||||
|
||||
protected int currentState = SBCS;
|
||||
|
||||
public Encoder_EBCDIC(Charset cs, char[] c2b, char[] c2bIndex) {
|
||||
super(cs, 4.0f, 5.0f, new byte[] {(byte)0x6f}, c2b, c2bIndex);
|
||||
public Encoder_EBCDIC(Charset cs, char[] c2b, char[] c2bIndex,
|
||||
boolean isASCIICompatible) {
|
||||
super(cs, 4.0f, 5.0f, new byte[] {(byte)0x6f}, c2b, c2bIndex, isASCIICompatible);
|
||||
}
|
||||
|
||||
protected void implReset() {
|
||||
@ -878,6 +974,7 @@ public class DoubleByte {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int encode(char[] src, int sp, int len, byte[] dst) {
|
||||
int dp = 0;
|
||||
int sl = sp + len;
|
||||
@ -917,12 +1014,88 @@ public class DoubleByte {
|
||||
}
|
||||
return dp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int encodeFromLatin1(byte[] src, int sp, int len, byte[] dst) {
|
||||
int dp = 0;
|
||||
int sl = sp + len;
|
||||
while (sp < sl) {
|
||||
char c = (char)(src[sp++] & 0xff);
|
||||
int bb = encodeChar(c);
|
||||
if (bb == UNMAPPABLE_ENCODING) {
|
||||
// no surrogate pair in latin1 string
|
||||
dst[dp++] = repl[0];
|
||||
if (repl.length > 1)
|
||||
dst[dp++] = repl[1];
|
||||
continue;
|
||||
} //else
|
||||
if (bb > MAX_SINGLEBYTE) { // DoubleByte
|
||||
if (currentState == SBCS) {
|
||||
currentState = DBCS;
|
||||
dst[dp++] = SO;
|
||||
}
|
||||
dst[dp++] = (byte)(bb >> 8);
|
||||
dst[dp++] = (byte)bb;
|
||||
} else { // SingleByte
|
||||
if (currentState == DBCS) {
|
||||
currentState = SBCS;
|
||||
dst[dp++] = SI;
|
||||
}
|
||||
dst[dp++] = (byte)bb;
|
||||
}
|
||||
}
|
||||
if (currentState == DBCS) {
|
||||
currentState = SBCS;
|
||||
dst[dp++] = SI;
|
||||
}
|
||||
return dp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int encodeFromUTF16(byte[] src, int sp, int len, byte[] dst) {
|
||||
int dp = 0;
|
||||
int sl = sp + len;
|
||||
while (sp < sl) {
|
||||
char c = StringUTF16.getChar(src, sp++);
|
||||
int bb = encodeChar(c);
|
||||
if (bb == UNMAPPABLE_ENCODING) {
|
||||
if (Character.isHighSurrogate(c) && sp < sl &&
|
||||
Character.isLowSurrogate(StringUTF16.getChar(src, sp))) {
|
||||
sp++;
|
||||
}
|
||||
dst[dp++] = repl[0];
|
||||
if (repl.length > 1)
|
||||
dst[dp++] = repl[1];
|
||||
continue;
|
||||
} //else
|
||||
if (bb > MAX_SINGLEBYTE) { // DoubleByte
|
||||
if (currentState == SBCS) {
|
||||
currentState = DBCS;
|
||||
dst[dp++] = SO;
|
||||
}
|
||||
dst[dp++] = (byte)(bb >> 8);
|
||||
dst[dp++] = (byte)bb;
|
||||
} else { // SingleByte
|
||||
if (currentState == DBCS) {
|
||||
currentState = SBCS;
|
||||
dst[dp++] = SI;
|
||||
}
|
||||
dst[dp++] = (byte)bb;
|
||||
}
|
||||
}
|
||||
if (currentState == DBCS) {
|
||||
currentState = SBCS;
|
||||
dst[dp++] = SI;
|
||||
}
|
||||
return dp;
|
||||
}
|
||||
}
|
||||
|
||||
// EUC_SIMPLE
|
||||
public static class Encoder_EUC_SIM extends Encoder {
|
||||
public Encoder_EUC_SIM(Charset cs, char[] c2b, char[] c2bIndex) {
|
||||
super(cs, c2b, c2bIndex);
|
||||
public Encoder_EUC_SIM(Charset cs, char[] c2b, char[] c2bIndex,
|
||||
boolean isASCIICompatible) {
|
||||
super(cs, c2b, c2bIndex, isASCIICompatible);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ public class HKSCS {
|
||||
// super(cs, 0.5f, 1.0f);
|
||||
// need to extends DoubleByte.Decoder so the
|
||||
// sun.io can use it. this implementation
|
||||
super(cs, 0.5f, 1.0f, null, null, 0, 0);
|
||||
super(cs, 0.5f, 1.0f, null, null, 0, 0, true);
|
||||
this.big5Dec = big5Dec;
|
||||
this.b2cBmp = b2cBmp;
|
||||
this.b2cSupp = b2cSupp;
|
||||
@ -239,7 +239,7 @@ public class HKSCS {
|
||||
char[][] c2bBmp,
|
||||
char[][] c2bSupp)
|
||||
{
|
||||
super(cs, null, null);
|
||||
super(cs, null, null, true);
|
||||
this.big5Enc = big5Enc;
|
||||
this.c2bBmp = c2bBmp;
|
||||
this.c2bSupp = c2bSupp;
|
||||
@ -389,6 +389,33 @@ public class HKSCS {
|
||||
return dp;
|
||||
}
|
||||
|
||||
public int encodeFromUTF16(byte[] src, int sp, int len, byte[] dst) {
|
||||
int dp = 0;
|
||||
int sl = sp + len;
|
||||
int dl = dst.length;
|
||||
while (sp < sl) {
|
||||
char c = StringUTF16.getChar(src, sp++);
|
||||
int bb = encodeChar(c);
|
||||
if (bb == UNMAPPABLE_ENCODING) {
|
||||
if (!Character.isHighSurrogate(c) || sp == sl ||
|
||||
!Character.isLowSurrogate(StringUTF16.getChar(src,sp)) ||
|
||||
(bb = encodeSupp(Character.toCodePoint(c, StringUTF16.getChar(src, sp++))))
|
||||
== UNMAPPABLE_ENCODING) {
|
||||
dst[dp++] = repl[0];
|
||||
if (repl.length > 1)
|
||||
dst[dp++] = repl[1];
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (bb > MAX_SINGLEBYTE) { // DoubleByte
|
||||
dst[dp++] = (byte)(bb >> 8);
|
||||
dst[dp++] = (byte)bb;
|
||||
} else { // SingleByte
|
||||
dst[dp++] = (byte)bb;
|
||||
}
|
||||
}
|
||||
return dp;
|
||||
}
|
||||
|
||||
static char[] C2B_UNMAPPABLE = new char[0x100];
|
||||
static {
|
||||
|
@ -132,6 +132,10 @@ class ISO_8859_1
|
||||
dst[dp++] = (char)(src[sp++] & 0xff);
|
||||
return dp;
|
||||
}
|
||||
|
||||
public boolean isASCIICompatible() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static class Encoder extends CharsetEncoder
|
||||
@ -297,5 +301,9 @@ class ISO_8859_1
|
||||
}
|
||||
return dp;
|
||||
}
|
||||
|
||||
public boolean isASCIICompatible() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -49,10 +49,18 @@ public class SingleByte
|
||||
public static final class Decoder extends CharsetDecoder
|
||||
implements ArrayDecoder {
|
||||
private final char[] b2c;
|
||||
private final boolean isASCIICompatible;
|
||||
|
||||
public Decoder(Charset cs, char[] b2c) {
|
||||
super(cs, 1.0f, 1.0f);
|
||||
this.b2c = b2c;
|
||||
this.isASCIICompatible = false;
|
||||
}
|
||||
|
||||
public Decoder(Charset cs, char[] b2c, boolean isASCIICompatible) {
|
||||
super(cs, 1.0f, 1.0f);
|
||||
this.b2c = b2c;
|
||||
this.isASCIICompatible = isASCIICompatible;
|
||||
}
|
||||
|
||||
private CoderResult decodeArrayLoop(ByteBuffer src, CharBuffer dst) {
|
||||
@ -116,6 +124,7 @@ public class SingleByte
|
||||
repl = newReplacement.charAt(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int decode(byte[] src, int sp, int len, char[] dst) {
|
||||
if (len > dst.length)
|
||||
len = dst.length;
|
||||
@ -129,6 +138,11 @@ public class SingleByte
|
||||
}
|
||||
return dp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isASCIICompatible() {
|
||||
return isASCIICompatible;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Encoder extends CharsetEncoder
|
||||
@ -136,11 +150,13 @@ public class SingleByte
|
||||
private Surrogate.Parser sgp;
|
||||
private final char[] c2b;
|
||||
private final char[] c2bIndex;
|
||||
private final boolean isASCIICompatible;
|
||||
|
||||
public Encoder(Charset cs, char[] c2b, char[] c2bIndex) {
|
||||
public Encoder(Charset cs, char[] c2b, char[] c2bIndex, boolean isASCIICompatible) {
|
||||
super(cs, 1.0f, 1.0f);
|
||||
this.c2b = c2b;
|
||||
this.c2bIndex = c2bIndex;
|
||||
this.isASCIICompatible = isASCIICompatible;
|
||||
}
|
||||
|
||||
public boolean canEncode(char c) {
|
||||
@ -252,6 +268,51 @@ public class SingleByte
|
||||
}
|
||||
return dp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int encodeFromLatin1(byte[] src, int sp, int len, byte[] dst) {
|
||||
int dp = 0;
|
||||
int sl = sp + Math.min(len, dst.length);
|
||||
while (sp < sl) {
|
||||
char c = (char)(src[sp++] & 0xff);
|
||||
int b = encode(c);
|
||||
if (b == UNMAPPABLE_ENCODING) {
|
||||
dst[dp++] = repl;
|
||||
} else {
|
||||
dst[dp++] = (byte)b;
|
||||
}
|
||||
}
|
||||
return dp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int encodeFromUTF16(byte[] src, int sp, int len, byte[] dst) {
|
||||
int dp = 0;
|
||||
int sl = sp + Math.min(len, dst.length);
|
||||
while (sp < sl) {
|
||||
char c = StringUTF16.getChar(src, sp++);
|
||||
int b = encode(c);
|
||||
if (b != UNMAPPABLE_ENCODING) {
|
||||
dst[dp++] = (byte)b;
|
||||
continue;
|
||||
}
|
||||
if (Character.isHighSurrogate(c) && sp < sl &&
|
||||
Character.isLowSurrogate(StringUTF16.getChar(src, sp))) {
|
||||
if (len > dst.length) {
|
||||
sl++;
|
||||
len--;
|
||||
}
|
||||
sp++;
|
||||
}
|
||||
dst[dp++] = repl;
|
||||
}
|
||||
return dp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isASCIICompatible() {
|
||||
return isASCIICompatible;
|
||||
}
|
||||
}
|
||||
|
||||
// init the c2b and c2bIndex tables from b2c.
|
||||
|
39
jdk/src/java.base/share/classes/sun/nio/cs/StringUTF16.java
Normal file
39
jdk/src/java.base/share/classes/sun/nio/cs/StringUTF16.java
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.nio.cs;
|
||||
|
||||
import static sun.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET;
|
||||
import static sun.misc.Unsafe.ARRAY_BYTE_INDEX_SCALE;
|
||||
|
||||
class StringUTF16 {
|
||||
|
||||
public static char getChar(byte[] val, int index) {
|
||||
return unsafe.getChar(val,
|
||||
ARRAY_BYTE_BASE_OFFSET + ARRAY_BYTE_INDEX_SCALE * index * 2L);
|
||||
}
|
||||
|
||||
private static final sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
|
||||
}
|
@ -146,6 +146,10 @@ public class US_ASCII
|
||||
}
|
||||
return dp;
|
||||
}
|
||||
|
||||
public boolean isASCIICompatible() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static class Encoder extends CharsetEncoder
|
||||
@ -259,6 +263,10 @@ public class US_ASCII
|
||||
}
|
||||
return dp;
|
||||
}
|
||||
|
||||
public boolean isASCIICompatible() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -549,6 +549,10 @@ class UTF_8 extends Unicode
|
||||
}
|
||||
return dp;
|
||||
}
|
||||
|
||||
public boolean isASCIICompatible() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class Encoder extends CharsetEncoder
|
||||
@ -742,5 +746,9 @@ class UTF_8 extends Unicode
|
||||
}
|
||||
return dp;
|
||||
}
|
||||
|
||||
public boolean isASCIICompatible() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,3 +31,14 @@ Java_java_lang_String_intern(JNIEnv *env, jobject this)
|
||||
{
|
||||
return JVM_InternString(env, this);
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_java_lang_StringUTF16_isBigEndian(JNIEnv *env, jclass cls)
|
||||
{
|
||||
unsigned int endianTest = 0xff000000;
|
||||
if (((char*)(&endianTest))[0] != 0) {
|
||||
return JNI_TRUE;
|
||||
} else {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
}
|
||||
|
@ -51,12 +51,12 @@ public class Big5_Solaris extends Charset implements HistoricallyNamedCharset
|
||||
|
||||
public CharsetDecoder newDecoder() {
|
||||
initb2c();
|
||||
return new DoubleByte.Decoder(this, b2c, b2cSB, 0x40, 0xfe);
|
||||
return new DoubleByte.Decoder(this, b2c, b2cSB, 0x40, 0xfe, true);
|
||||
}
|
||||
|
||||
public CharsetEncoder newEncoder() {
|
||||
initc2b();
|
||||
return new DoubleByte.Encoder(this, c2b, c2bIndex);
|
||||
return new DoubleByte.Encoder(this, c2b, c2bIndex, true);
|
||||
}
|
||||
|
||||
static char[][] b2c;
|
||||
|
@ -62,7 +62,7 @@ public class IBM834 extends Charset
|
||||
protected static class Encoder extends DoubleByte.Encoder_DBCSONLY {
|
||||
public Encoder(Charset cs) {
|
||||
super(cs, new byte[] {(byte)0xfe, (byte)0xfe},
|
||||
IBM933.c2b, IBM933.c2bIndex);
|
||||
IBM933.c2b, IBM933.c2bIndex, false);
|
||||
}
|
||||
|
||||
public int encodeChar(char ch) {
|
||||
|
89
jdk/test/java/lang/String/Chars.java
Normal file
89
jdk/test/java/lang/String/Chars.java
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
@test
|
||||
@bug 8054307
|
||||
@summary test chars() and codePoints()
|
||||
*/
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
|
||||
public class Chars {
|
||||
|
||||
public static void main(String[] args) {
|
||||
Random r = new Random();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
int n = 100 + r.nextInt(100);
|
||||
char[] cc = new char[n];
|
||||
int[] ccExp = new int[n];
|
||||
int[] cpExp = new int[n];
|
||||
// latin1
|
||||
for (int j = 0; j < n; j++) {
|
||||
cc[j] = (char)(ccExp[j] = cpExp[j] = r.nextInt(0x80));
|
||||
}
|
||||
testChars(cc, ccExp);
|
||||
testCPs(cc, cpExp);
|
||||
|
||||
// bmp without surrogates
|
||||
for (int j = 0; j < n; j++) {
|
||||
cc[j] = (char)(ccExp[j] = cpExp[j] = r.nextInt(0x8000));
|
||||
}
|
||||
testChars(cc, ccExp);
|
||||
testCPs(cc, cpExp);
|
||||
|
||||
// bmp with surrogates
|
||||
int k = 0;
|
||||
for (int j = 0; j < n; j++) {
|
||||
if (j % 9 == 5 && j + 1 < n) {
|
||||
int cp = 0x10000 + r.nextInt(2000);
|
||||
cpExp[k++] = cp;
|
||||
Character.toChars(cp, cc, j);
|
||||
ccExp[j] = cc[j];
|
||||
ccExp[j + 1] = cc[j + 1];
|
||||
j++;
|
||||
} else {
|
||||
cc[j] = (char)(ccExp[j] = cpExp[k++] = r.nextInt(0x8000));
|
||||
}
|
||||
}
|
||||
cpExp = Arrays.copyOf(cpExp, k);
|
||||
testChars(cc, ccExp);
|
||||
testCPs(cc, cpExp);
|
||||
}
|
||||
}
|
||||
|
||||
static void testChars(char[] cc, int[] expected) {
|
||||
String str = new String(cc);
|
||||
if (!Arrays.equals(expected, str.chars().toArray())) {
|
||||
throw new RuntimeException("chars/codePoints() failed!");
|
||||
}
|
||||
}
|
||||
|
||||
static void testCPs(char[] cc, int[] expected) {
|
||||
String str = new String(cc);
|
||||
if (!Arrays.equals(expected, str.codePoints().toArray())) {
|
||||
throw new RuntimeException("chars/codePoints() failed!");
|
||||
}
|
||||
}
|
||||
}
|
72
jdk/test/java/lang/String/CompactString/CharAt.java
Normal file
72
jdk/test/java/lang/String/CompactString/CharAt.java
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8077559
|
||||
* @summary Tests Compact String. This one is for String.charAt.
|
||||
* @run testng/othervm -XX:+CompactStrings CharAt
|
||||
* @run testng/othervm -XX:-CompactStrings CharAt
|
||||
*/
|
||||
|
||||
public class CharAt extends CompactString {
|
||||
|
||||
@DataProvider
|
||||
public Object[][] provider() {
|
||||
return new Object[][] {
|
||||
new Object[] { STRING_L1, new char[] { 'A' } },
|
||||
new Object[] { STRING_L2, new char[] { 'A', 'B' } },
|
||||
new Object[] { STRING_L4, new char[] { 'A', 'B', 'C', 'D' } },
|
||||
new Object[] { STRING_LLONG,
|
||||
new char[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' } },
|
||||
new Object[] { STRING_U1, new char[] { '\uFF21' } },
|
||||
new Object[] { STRING_U2, new char[] { '\uFF21', '\uFF22' } },
|
||||
new Object[] { STRING_M12, new char[] { '\uFF21', 'A' } },
|
||||
new Object[] { STRING_M11, new char[] { 'A', '\uFF21' } }, };
|
||||
}
|
||||
|
||||
@Test(dataProvider = "provider")
|
||||
public void testCharAt(String str, char[] expected) {
|
||||
map.get(str)
|
||||
.forEach(
|
||||
(source, data) -> {
|
||||
IntStream
|
||||
.range(0, str.length())
|
||||
.forEach(
|
||||
i -> assertEquals(
|
||||
str.charAt(i),
|
||||
expected[i],
|
||||
String.format(
|
||||
"testing String(%s).charAt(%d), source : %s, ",
|
||||
escapeNonASCIIs(data),
|
||||
i, source)));
|
||||
});
|
||||
}
|
||||
}
|
79
jdk/test/java/lang/String/CompactString/CodePointAt.java
Normal file
79
jdk/test/java/lang/String/CompactString/CodePointAt.java
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8077559
|
||||
* @summary Tests Compact String. This one is for String.codePointAt.
|
||||
* @run testng/othervm -XX:+CompactStrings CodePointAt
|
||||
* @run testng/othervm -XX:-CompactStrings CodePointAt
|
||||
*/
|
||||
|
||||
public class CodePointAt extends CompactString {
|
||||
|
||||
@DataProvider
|
||||
public Object[][] provider() {
|
||||
return new Object[][] {
|
||||
|
||||
new Object[] { STRING_L1, new int[] { 'A' } },
|
||||
new Object[] { STRING_L2, new int[] { 'A', 'B' } },
|
||||
new Object[] { STRING_L4, new int[] { 'A', 'B', 'C', 'D' } },
|
||||
new Object[] { STRING_LLONG,
|
||||
new int[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' } },
|
||||
new Object[] { STRING_U1, new int[] { '\uFF21' } },
|
||||
new Object[] { STRING_U2, new int[] { '\uFF21', '\uFF22' } },
|
||||
new Object[] { STRING_M12, new int[] { '\uFF21', 'A' } },
|
||||
new Object[] { STRING_M11, new int[] { 'A', '\uFF21' } },
|
||||
new Object[] {
|
||||
STRING_SUPPLEMENTARY,
|
||||
new int[] { Character.toCodePoint('\uD801', '\uDC00'),
|
||||
'\uDC00',
|
||||
Character.toCodePoint('\uD801', '\uDC01'),
|
||||
'\uDC01', '\uFF21', 'A' }, } };
|
||||
}
|
||||
|
||||
@Test(dataProvider = "provider")
|
||||
public void testCodePointAt(String str, int[] expected) {
|
||||
map.get(str)
|
||||
.forEach(
|
||||
(source, data) -> {
|
||||
IntStream
|
||||
.range(0, str.length())
|
||||
.forEach(
|
||||
i -> assertEquals(
|
||||
str.codePointAt(i),
|
||||
expected[i],
|
||||
String.format(
|
||||
"testing String(%s).codePointAt(%d), source : %s, ",
|
||||
escapeNonASCIIs(data),
|
||||
i, source)));
|
||||
});
|
||||
}
|
||||
}
|
79
jdk/test/java/lang/String/CompactString/CodePointBefore.java
Normal file
79
jdk/test/java/lang/String/CompactString/CodePointBefore.java
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8077559
|
||||
* @summary Tests Compact String. This one is for String.codePointBefore.
|
||||
* @run testng/othervm -XX:+CompactStrings CodePointBefore
|
||||
* @run testng/othervm -XX:-CompactStrings CodePointBefore
|
||||
*/
|
||||
|
||||
public class CodePointBefore extends CompactString {
|
||||
|
||||
@DataProvider
|
||||
public Object[][] provider() {
|
||||
return new Object[][] {
|
||||
|
||||
new Object[] { STRING_L1, new int[] { 'A' } },
|
||||
new Object[] { STRING_L2, new int[] { 'A', 'B' } },
|
||||
new Object[] { STRING_L4, new int[] { 'A', 'B', 'C', 'D' } },
|
||||
new Object[] { STRING_LLONG,
|
||||
new int[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' } },
|
||||
new Object[] { STRING_U1, new int[] { '\uFF21' } },
|
||||
new Object[] { STRING_U2, new int[] { '\uFF21', '\uFF22' } },
|
||||
new Object[] { STRING_M12, new int[] { '\uFF21', 'A' } },
|
||||
new Object[] { STRING_M11, new int[] { 'A', '\uFF21' } },
|
||||
new Object[] {
|
||||
STRING_SUPPLEMENTARY,
|
||||
new int[] { '\uD801', Character.toCodePoint('\uD801', '\uDC00'),
|
||||
'\uD801', Character.toCodePoint('\uD801', '\uDC01'),
|
||||
'\uFF21', 'A' }, } };
|
||||
}
|
||||
|
||||
@Test(dataProvider = "provider")
|
||||
public void testCodePointBefore(String str, int[] expected) {
|
||||
map.get(str)
|
||||
.forEach(
|
||||
(source, data) -> {
|
||||
IntStream
|
||||
.range(0, str.length())
|
||||
.forEach(
|
||||
i -> assertEquals(
|
||||
str.codePointBefore(i + 1),
|
||||
expected[i],
|
||||
String.format(
|
||||
"testing String(%s).codePointBefore(%d), source : %s, ",
|
||||
escapeNonASCIIs(data),
|
||||
i + 1, source)));
|
||||
});
|
||||
}
|
||||
|
||||
}
|
89
jdk/test/java/lang/String/CompactString/CodePointCount.java
Normal file
89
jdk/test/java/lang/String/CompactString/CodePointCount.java
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8077559
|
||||
* @summary Tests Compact String. This one is for String.codePointCount.
|
||||
* @run testng/othervm -XX:+CompactStrings CodePointCount
|
||||
* @run testng/othervm -XX:-CompactStrings CodePointCount
|
||||
*/
|
||||
|
||||
public class CodePointCount extends CompactString {
|
||||
|
||||
@DataProvider
|
||||
public Object[][] provider() {
|
||||
return new Object[][] { new Object[] { STRING_EMPTY, 0, 0, 0 },
|
||||
new Object[] { STRING_L1, 0, 1, 1 },
|
||||
new Object[] { STRING_L1, 1, 1, 0 },
|
||||
new Object[] { STRING_L2, 0, 2, 2 },
|
||||
new Object[] { STRING_L2, 0, 1, 1 },
|
||||
new Object[] { STRING_L2, 1, 2, 1 },
|
||||
new Object[] { STRING_L4, 0, 4, 4 },
|
||||
new Object[] { STRING_L4, 0, 1, 1 },
|
||||
new Object[] { STRING_L4, 2, 4, 2 },
|
||||
new Object[] { STRING_LLONG, 0, 8, 8 },
|
||||
new Object[] { STRING_LLONG, 0, 5, 5 },
|
||||
new Object[] { STRING_LLONG, 4, 8, 4 },
|
||||
new Object[] { STRING_LLONG, 0, 7, 7 },
|
||||
new Object[] { STRING_U1, 0, 1, 1 },
|
||||
new Object[] { STRING_U2, 0, 2, 2 },
|
||||
new Object[] { STRING_U2, 0, 1, 1 },
|
||||
new Object[] { STRING_U2, 1, 2, 1 },
|
||||
new Object[] { STRING_M12, 0, 2, 2 },
|
||||
new Object[] { STRING_M12, 0, 1, 1 },
|
||||
new Object[] { STRING_M12, 1, 2, 1 },
|
||||
new Object[] { STRING_M11, 0, 2, 2 },
|
||||
new Object[] { STRING_M11, 0, 1, 1 },
|
||||
new Object[] { STRING_M11, 1, 2, 1 },
|
||||
new Object[] { STRING_SUPPLEMENTARY, 0, 1, 1 },
|
||||
new Object[] { STRING_SUPPLEMENTARY, 0, 2, 1 },
|
||||
new Object[] { STRING_SUPPLEMENTARY, 0, 3, 2 },
|
||||
new Object[] { STRING_SUPPLEMENTARY, 0, 5, 3 },
|
||||
new Object[] { STRING_SUPPLEMENTARY, 0, 6, 4 },
|
||||
new Object[] { STRING_SUPPLEMENTARY, 1, 4, 2 },
|
||||
new Object[] { STRING_SUPPLEMENTARY, 1, 6, 4 },
|
||||
new Object[] { STRING_SUPPLEMENTARY, 2, 4, 1 },};
|
||||
}
|
||||
|
||||
@Test(dataProvider = "provider")
|
||||
public void testCodePointCount(String str, int beginIndex, int endIndex,
|
||||
int expected) {
|
||||
map.get(str)
|
||||
.forEach(
|
||||
(source, data) -> {
|
||||
assertEquals(
|
||||
data.codePointCount(beginIndex, endIndex),
|
||||
expected,
|
||||
String.format(
|
||||
"testing String(%s).codePointCount(%d, %d), source : %s, ",
|
||||
escapeNonASCIIs(data), beginIndex,
|
||||
endIndex, source));
|
||||
});
|
||||
}
|
||||
}
|
307
jdk/test/java/lang/String/CompactString/CompactString.java
Normal file
307
jdk/test/java/lang/String/CompactString/CompactString.java
Normal file
@ -0,0 +1,307 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.testng.annotations.BeforeClass;
|
||||
|
||||
/*
|
||||
* Base class of tests for Compact String.
|
||||
*
|
||||
*/
|
||||
public class CompactString {
|
||||
|
||||
final Map<String, Map<String, String>> map = new HashMap<>();
|
||||
|
||||
enum StringSources {
|
||||
EMPTY(STRING_EMPTY, BYTE_ARRAY_EMTPY, CHAR_ARRAY_EMPTY,
|
||||
POINT_ARRAY_EMTPY), LDUPLICATE(STRING_LDUPLICATE,
|
||||
BYTE_ARRAY_LDUPLICATE, CHAR_ARRAY_LDUPLICATE,
|
||||
POINT_ARRAY_LDUPLICATE), LLONG(STRING_LLONG, BYTE_ARRAY_LLONG,
|
||||
CHAR_ARRAY_LLONG, POINT_ARRAY_LLONG), L1(STRING_L1,
|
||||
BYTE_ARRAY_L1, CHAR_ARRAY_L1, POINT_ARRAY_L1), L2(STRING_L2,
|
||||
BYTE_ARRAY_L2, CHAR_ARRAY_L2, POINT_ARRAY_L2), L4(STRING_L4,
|
||||
BYTE_ARRAY_L4, CHAR_ARRAY_L4, POINT_ARRAY_L4), UDUPLICATE(
|
||||
STRING_UDUPLICATE, BYTE_ARRAY_UDUPLICATE,
|
||||
CHAR_ARRAY_UDUPLICATE, POINT_ARRAY_UDUPLICATE), U1(STRING_U1,
|
||||
BYTE_ARRAY_U1, CHAR_ARRAY_U1, POINT_ARRAY_U1), U2(STRING_U2,
|
||||
BYTE_ARRAY_U2, CHAR_ARRAY_U2, POINT_ARRAY_U2), MDUPLICATE1(
|
||||
STRING_MDUPLICATE1, BYTE_ARRAY_MDUPLICATE1,
|
||||
CHAR_ARRAY_MDUPLICATE1, POINT_ARRAY_MDUPLICATE1), MDUPLICATE2(
|
||||
STRING_MDUPLICATE2, BYTE_ARRAY_MDUPLICATE2,
|
||||
CHAR_ARRAY_MDUPLICATE2, POINT_ARRAY_MDUPLICATE2), MLONG1(
|
||||
STRING_MLONG1, BYTE_ARRAY_MLONG1, CHAR_ARRAY_MLONG1,
|
||||
POINT_ARRAY_MLONG1), MLONG2(STRING_MLONG2, BYTE_ARRAY_MLONG2,
|
||||
CHAR_ARRAY_MLONG2, POINT_ARRAY_MLONG2), M11(STRING_M11,
|
||||
BYTE_ARRAY_M11, CHAR_ARRAY_M11, POINT_ARRAY_M11), M12(
|
||||
STRING_M12, BYTE_ARRAY_M12, CHAR_ARRAY_M12, POINT_ARRAY_M12), SUPPLEMENTARY(
|
||||
STRING_SUPPLEMENTARY, BYTE_ARRAY_SUPPLEMENTARY,
|
||||
CHAR_ARRAY_SUPPLEMENTARY, POINT_ARRAY_SUPPLEMENTARY), SUPPLEMENTARY_LOWERCASE(
|
||||
STRING_SUPPLEMENTARY_LOWERCASE,
|
||||
BYTE_ARRAY_SUPPLEMENTARY_LOWERCASE,
|
||||
CHAR_ARRAY_SUPPLEMENTARY_LOWERCASE,
|
||||
POINT_ARRAY_SUPPLEMENTARY_LOWERCASE);
|
||||
|
||||
private StringSources(String s, byte[] b, char[] c, int[] i) {
|
||||
str = s;
|
||||
ba = b;
|
||||
ca = c;
|
||||
ia = i;
|
||||
}
|
||||
|
||||
String getString() {
|
||||
return str;
|
||||
}
|
||||
|
||||
byte[] getByteArray() {
|
||||
return ba;
|
||||
}
|
||||
|
||||
char[] getCharArray() {
|
||||
return ca;
|
||||
}
|
||||
|
||||
int[] getIntArray() {
|
||||
return ia;
|
||||
}
|
||||
|
||||
private final String str;
|
||||
private final byte[] ba;
|
||||
private final char[] ca;
|
||||
private final int[] ia;
|
||||
}
|
||||
|
||||
protected static final String DEFAULT_CHARSET_NAME = "UTF-8";
|
||||
protected static final Charset DEFAULT_CHARSET = Charset
|
||||
.forName(DEFAULT_CHARSET_NAME);
|
||||
|
||||
protected static final String STRING_EMPTY = "";
|
||||
protected static final byte[] BYTE_ARRAY_EMTPY = new byte[0];
|
||||
protected static final char[] CHAR_ARRAY_EMPTY = new char[0];
|
||||
protected static final int[] POINT_ARRAY_EMTPY = new int[0];
|
||||
|
||||
protected static final String STRING_LDUPLICATE = "ABABABABAB";
|
||||
protected static final byte[] BYTE_ARRAY_LDUPLICATE = new byte[] { 'A', 'B',
|
||||
'A', 'B', 'A', 'B', 'A', 'B', 'A', 'B' };
|
||||
protected static final char[] CHAR_ARRAY_LDUPLICATE = new char[] { 'A', 'B',
|
||||
'A', 'B', 'A', 'B', 'A', 'B', 'A', 'B' };
|
||||
protected static final int[] POINT_ARRAY_LDUPLICATE = new int[] { 'A', 'B',
|
||||
'A', 'B', 'A', 'B', 'A', 'B', 'A', 'B' };
|
||||
|
||||
protected static final String STRING_LLONG = "ABCDEFGH";
|
||||
protected static final byte[] BYTE_ARRAY_LLONG = new byte[] { 'A', 'B', 'C',
|
||||
'D', 'E', 'F', 'G', 'H' };
|
||||
protected static final char[] CHAR_ARRAY_LLONG = new char[] { 'A', 'B', 'C',
|
||||
'D', 'E', 'F', 'G', 'H' };
|
||||
protected static final int[] POINT_ARRAY_LLONG = new int[] { 'A', 'B', 'C',
|
||||
'D', 'E', 'F', 'G', 'H' };
|
||||
|
||||
protected static final String STRING_L1 = "A";
|
||||
protected static final byte[] BYTE_ARRAY_L1 = new byte[] { 'A' };
|
||||
protected static final char[] CHAR_ARRAY_L1 = new char[] { 'A' };
|
||||
protected static final int[] POINT_ARRAY_L1 = new int[] { 'A' };
|
||||
|
||||
protected static final String STRING_L2 = "AB";
|
||||
protected static final byte[] BYTE_ARRAY_L2 = new byte[] { 'A', 'B' };
|
||||
protected static final char[] CHAR_ARRAY_L2 = new char[] { 'A', 'B' };
|
||||
protected static final int[] POINT_ARRAY_L2 = new int[] { 'A', 'B' };
|
||||
|
||||
protected static final String STRING_L4 = "ABCD";
|
||||
protected static final byte[] BYTE_ARRAY_L4 = new byte[] { 'A', 'B', 'C', 'D' };
|
||||
protected static final char[] CHAR_ARRAY_L4 = new char[] { 'A', 'B', 'C', 'D' };
|
||||
protected static final int[] POINT_ARRAY_L4 = new int[] { 'A', 'B', 'C', 'D' };
|
||||
|
||||
/*
|
||||
* Because right now ASCII is the default encoding parameter for source code
|
||||
* in JDK build environment, so we escape them. same as below.
|
||||
*/
|
||||
protected static final String STRING_UDUPLICATE = "\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22";
|
||||
protected static final byte[] BYTE_ARRAY_UDUPLICATE = getBytes(STRING_UDUPLICATE);
|
||||
protected static final char[] CHAR_ARRAY_UDUPLICATE = new char[] { '\uFF21',
|
||||
'\uFF22', '\uFF21', '\uFF22', '\uFF21', '\uFF22', '\uFF21',
|
||||
'\uFF22', '\uFF21', '\uFF22' };
|
||||
protected static final int[] POINT_ARRAY_UDUPLICATE = new int[] { '\uFF21',
|
||||
'\uFF22', '\uFF21', '\uFF22', '\uFF21', '\uFF22', '\uFF21',
|
||||
'\uFF22', '\uFF21', '\uFF22' };
|
||||
|
||||
protected static final String STRING_U1 = "\uFF21";
|
||||
protected static final byte[] BYTE_ARRAY_U1 = getBytes(STRING_U1);
|
||||
protected static final char[] CHAR_ARRAY_U1 = new char[] { '\uFF21' };
|
||||
protected static final int[] POINT_ARRAY_U1 = new int[] { '\uFF21' };
|
||||
|
||||
protected static final String STRING_U2 = "\uFF21\uFF22";
|
||||
protected static final byte[] BYTE_ARRAY_U2 = getBytes(STRING_U2);
|
||||
protected static final char[] CHAR_ARRAY_U2 = new char[] { '\uFF21', '\uFF22' };
|
||||
protected static final int[] POINT_ARRAY_U2 = new int[] { '\uFF21', '\uFF22' };
|
||||
|
||||
protected static final String STRING_MDUPLICATE1 = "\uFF21A\uFF21A\uFF21A\uFF21A\uFF21A";
|
||||
protected static final byte[] BYTE_ARRAY_MDUPLICATE1 = getBytes(STRING_MDUPLICATE1);
|
||||
protected static final char[] CHAR_ARRAY_MDUPLICATE1 = new char[] { '\uFF21',
|
||||
'A', '\uFF21', 'A', '\uFF21', 'A', '\uFF21', 'A', '\uFF21', 'A' };
|
||||
protected static final int[] POINT_ARRAY_MDUPLICATE1 = new int[] { '\uFF21',
|
||||
'A', '\uFF21', 'A', '\uFF21', 'A', '\uFF21', 'A', '\uFF21', 'A' };
|
||||
|
||||
protected static final String STRING_MDUPLICATE2 = "A\uFF21A\uFF21A\uFF21A\uFF21A\uFF21";
|
||||
protected static final byte[] BYTE_ARRAY_MDUPLICATE2 = getBytes(STRING_MDUPLICATE2);
|
||||
protected static final char[] CHAR_ARRAY_MDUPLICATE2 = new char[] { 'A',
|
||||
'\uFF21', 'A', '\uFF21', 'A', '\uFF21', 'A', '\uFF21', 'A',
|
||||
'\uFF21' };
|
||||
protected static final int[] POINT_ARRAY_MDUPLICATE2 = new int[] { 'A',
|
||||
'\uFF21', 'A', '\uFF21', 'A', '\uFF21', 'A', '\uFF21', 'A',
|
||||
'\uFF21' };
|
||||
|
||||
protected static final String STRING_MLONG1 = "A\uFF21B\uFF22C\uFF23D\uFF24E\uFF25F\uFF26G\uFF27H\uFF28";
|
||||
protected static final byte[] BYTE_ARRAY_MLONG1 = getBytes(STRING_MLONG1);
|
||||
protected static final char[] CHAR_ARRAY_MLONG1 = new char[] { 'A', '\uFF21',
|
||||
'B', '\uFF22', 'C', '\uFF23', 'D', '\uFF24', 'E', '\uFF25', 'F',
|
||||
'\uFF26', 'G', '\uFF27', 'H', '\uFF28' };
|
||||
protected static final int[] POINT_ARRAY_MLONG1 = new int[] { 'A', '\uFF21',
|
||||
'B', '\uFF22', 'C', '\uFF23', 'D', '\uFF24', 'E', '\uFF25', 'F',
|
||||
'\uFF26', 'G', '\uFF27', 'H', '\uFF28' };
|
||||
|
||||
protected static final String STRING_MLONG2 = "\uFF21A\uFF22B\uFF23C\uFF24D\uFF25E\uFF26F\uFF27G\uFF28H";
|
||||
protected static final byte[] BYTE_ARRAY_MLONG2 = getBytes(STRING_MLONG2);
|
||||
protected static final char[] CHAR_ARRAY_MLONG2 = new char[] { '\uFF21', 'A',
|
||||
'\uFF22', 'B', '\uFF23', 'C', '\uFF24', 'D', '\uFF25', 'E',
|
||||
'\uFF26', 'F', '\uFF27', 'G', '\uFF28', 'H' };
|
||||
protected static final int[] POINT_ARRAY_MLONG2 = new int[] { '\uFF21', 'A',
|
||||
'\uFF22', 'B', '\uFF23', 'C', '\uFF24', 'D', '\uFF25', 'E',
|
||||
'\uFF26', 'F', '\uFF27', 'G', '\uFF28', 'H' };
|
||||
|
||||
protected static final String STRING_M11 = "A\uFF21";
|
||||
protected static final byte[] BYTE_ARRAY_M11 = getBytes(STRING_M11);
|
||||
protected static final char[] CHAR_ARRAY_M11 = new char[] { 'A', '\uFF21' };
|
||||
protected static final int[] POINT_ARRAY_M11 = new int[] { 'A', '\uFF21' };
|
||||
|
||||
protected static final String STRING_M12 = "\uFF21A";
|
||||
protected static final byte[] BYTE_ARRAY_M12 = getBytes(STRING_M12);
|
||||
protected static final char[] CHAR_ARRAY_M12 = new char[] { '\uFF21', 'A' };
|
||||
protected static final int[] POINT_ARRAY_M12 = new int[] { '\uFF21', 'A' };
|
||||
|
||||
protected static final String STRING_SUPPLEMENTARY = "\uD801\uDC00\uD801\uDC01\uFF21A";
|
||||
protected static final byte[] BYTE_ARRAY_SUPPLEMENTARY = getBytes(STRING_SUPPLEMENTARY);
|
||||
protected static final char[] CHAR_ARRAY_SUPPLEMENTARY = new char[] {
|
||||
'\uD801', '\uDC00', '\uD801', '\uDC01', '\uFF21', 'A' };
|
||||
protected static final int[] POINT_ARRAY_SUPPLEMENTARY = new int[] {
|
||||
'\uD801', '\uDC00', '\uD801', '\uDC01', '\uFF21', 'A' };
|
||||
|
||||
protected static final String STRING_SUPPLEMENTARY_LOWERCASE = "\uD801\uDC28\uD801\uDC29\uFF41a";
|
||||
protected static final byte[] BYTE_ARRAY_SUPPLEMENTARY_LOWERCASE = getBytes(STRING_SUPPLEMENTARY_LOWERCASE);
|
||||
protected static final char[] CHAR_ARRAY_SUPPLEMENTARY_LOWERCASE = new char[] {
|
||||
'\uD801', '\uDC28', '\uD801', '\uDC29', '\uFF41', 'a' };
|
||||
protected static final int[] POINT_ARRAY_SUPPLEMENTARY_LOWERCASE = new int[] {
|
||||
'\uD801', '\uDC28', '\uD801', '\uDC29', '\uFF41', 'a' };
|
||||
|
||||
protected static final String SRC_BYTE_ARRAY_WITH_CHARSETNAME = "source from byte array with charset name";
|
||||
protected static final String SRC_BYTE_ARRAY_WITH_CHARSET = "source from byte array with charset";
|
||||
protected static final String SRC_CHAR_ARRAY = "source from char array";
|
||||
protected static final String SRC_POINT_ARRAY = "source from code point array";
|
||||
protected static final String SRC_STRING = "source from String";
|
||||
protected static final String SRC_STRINGBUFFER = "source from StringBuffer";
|
||||
protected static final String SRC_STRINGBUILDER = "source from StringBuilder";
|
||||
protected static final String SRC_COPYVALUEOF = "source from copyValueOf from char array";
|
||||
protected static final String SRC_VALUEOF = "source from valueOf from char array";
|
||||
|
||||
static {
|
||||
System.out
|
||||
.println(String
|
||||
.format("====== The platform's default charset is \"%s\", we're using \"%s\" for testing.",
|
||||
Charset.defaultCharset().name(),
|
||||
DEFAULT_CHARSET_NAME));
|
||||
}
|
||||
|
||||
private static byte[] getBytes(String str) {
|
||||
byte[] res = null;
|
||||
try {
|
||||
res = str.getBytes(DEFAULT_CHARSET_NAME);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException("caught UnsupportedEncodingException!!!", e);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private void setUpOneString(String content, byte[] ba, char[] ca, int[] cpa)
|
||||
throws UnsupportedEncodingException {
|
||||
final Map<String, String> m = new HashMap<>();
|
||||
m.put(SRC_BYTE_ARRAY_WITH_CHARSETNAME, new String(ba,
|
||||
DEFAULT_CHARSET_NAME));
|
||||
m.put(SRC_BYTE_ARRAY_WITH_CHARSET, new String(ba, DEFAULT_CHARSET));
|
||||
m.put(SRC_CHAR_ARRAY, new String(ca));
|
||||
m.put(SRC_POINT_ARRAY, new String(cpa, 0, cpa.length));
|
||||
m.put(SRC_STRING, new String(content));
|
||||
m.put(SRC_STRINGBUFFER, new String(new StringBuffer(content)));
|
||||
m.put(SRC_STRINGBUILDER, new String(new StringBuilder(content)));
|
||||
m.put(SRC_COPYVALUEOF, String.copyValueOf(ca));
|
||||
m.put(SRC_VALUEOF, String.valueOf(ca));
|
||||
map.put(content, m);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up the test data, use 9 ways to construct one String.
|
||||
*
|
||||
* @throws UnsupportedEncodingException
|
||||
* If the named charset is not supported in setUpOneString(xxx).
|
||||
*/
|
||||
@BeforeClass
|
||||
public void setUp() throws UnsupportedEncodingException {
|
||||
for (StringSources src : StringSources.values()) {
|
||||
setUpOneString(src.getString(), src.getByteArray(),
|
||||
src.getCharArray(), src.getIntArray());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Because right now system default charset in JPRT environment is only
|
||||
* guaranteed to support ASCII characters in log, so we escape them.
|
||||
*/
|
||||
protected String escapeNonASCIIs(String str) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < str.length(); i++) {
|
||||
char c = str.charAt(i);
|
||||
if (c > 0x7F) {
|
||||
sb.append("\\u").append(Integer.toHexString((int) c));
|
||||
} else {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* Because right now system default charset in JPRT environment is only
|
||||
* guaranteed to support ASCII characters in log, so we escape them.
|
||||
*/
|
||||
protected String escapeNonASCII(char c) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (c > 0x7F) {
|
||||
sb.append("\\u").append(Integer.toHexString((int) c));
|
||||
} else {
|
||||
sb.append(c);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
94
jdk/test/java/lang/String/CompactString/CompareTo.java
Normal file
94
jdk/test/java/lang/String/CompactString/CompareTo.java
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8077559
|
||||
* @summary Tests Compact String. This one is for String.compareTo.
|
||||
* @run testng/othervm -XX:+CompactStrings CompareTo
|
||||
* @run testng/othervm -XX:-CompactStrings CompareTo
|
||||
*/
|
||||
|
||||
public class CompareTo extends CompactString {
|
||||
|
||||
@DataProvider
|
||||
public Object[][] provider() {
|
||||
return new Object[][] {
|
||||
|
||||
new Object[] { STRING_EMPTY, "A", -1 },
|
||||
new Object[] { STRING_EMPTY, "\uFF21", -1 },
|
||||
new Object[] { STRING_L1, "AB", -1 },
|
||||
new Object[] { STRING_L1, "A", 0 },
|
||||
new Object[] { STRING_L1, "a", -32 },
|
||||
new Object[] { STRING_L1, "\uFF21", -65248 },
|
||||
new Object[] { STRING_L2, "AB", 0 },
|
||||
new Object[] { STRING_L2, "Ab", -32 },
|
||||
new Object[] { STRING_L2, "AA", 1 },
|
||||
new Object[] { STRING_L2, "\uFF21", -65248 },
|
||||
new Object[] { STRING_L2, "A\uFF21", -65247 },
|
||||
new Object[] { STRING_L4, "ABC", 1 },
|
||||
new Object[] { STRING_L4, "AB", 2 },
|
||||
new Object[] { STRING_L4, "ABcD", -32 },
|
||||
new Object[] { STRING_L4, "ABCD\uFF21\uFF21", -2 },
|
||||
new Object[] { STRING_L4, "ABCD\uFF21", -1 },
|
||||
new Object[] { STRING_LLONG, "ABCDEFG\uFF21", -65241 },
|
||||
new Object[] { STRING_LLONG, "AB", 6 },
|
||||
new Object[] { STRING_LLONG, "ABCD", 4 },
|
||||
new Object[] { STRING_LLONG, "ABCDEFGH\uFF21\uFF21", -2 },
|
||||
new Object[] { STRING_U1, "\uFF21", 0 },
|
||||
new Object[] { STRING_U1, "\uFF22", -1 },
|
||||
new Object[] { STRING_U1, "\uFF21\uFF22", -1 },
|
||||
new Object[] { STRING_U1, "A", 65248 },
|
||||
new Object[] { STRING_U2, "\uFF21\uFF22", 0 },
|
||||
new Object[] { STRING_U2, "\uFF22", -1 },
|
||||
new Object[] { STRING_U2, "\uFF21\uFF21", 1 },
|
||||
new Object[] { STRING_U2, "A", 65248 },
|
||||
new Object[] { STRING_M12, "\uFF21A", 0 },
|
||||
new Object[] { STRING_M12, "A\uFF21", 65248 },
|
||||
new Object[] { STRING_M12, "\uFF21\uFF21", -65248 },
|
||||
new Object[] { STRING_M11, "A\uFF21", 0 },
|
||||
new Object[] { STRING_M11, "\uFF21A", -65248 },
|
||||
new Object[] { STRING_M11, "AA", 65248 }, };
|
||||
}
|
||||
|
||||
@Test(dataProvider = "provider")
|
||||
public void testCompareTo(String str, String anotherString, int expected) {
|
||||
map.get(str)
|
||||
.forEach(
|
||||
(source, data) -> {
|
||||
assertEquals(
|
||||
data.compareTo(anotherString),
|
||||
expected,
|
||||
String.format(
|
||||
"testing String(%s).compareTo(%s), source : %s, ",
|
||||
escapeNonASCIIs(data),
|
||||
escapeNonASCIIs(anotherString),
|
||||
source));
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8077559
|
||||
* @summary Tests Compact String. This one is for String.compareToIgnoreCase.
|
||||
* @run testng/othervm -XX:+CompactStrings CompareToIgnoreCase
|
||||
* @run testng/othervm -XX:-CompactStrings CompareToIgnoreCase
|
||||
*/
|
||||
|
||||
public class CompareToIgnoreCase extends CompactString {
|
||||
|
||||
@DataProvider
|
||||
public Object[][] provider() {
|
||||
return new Object[][] {
|
||||
|
||||
new Object[] { STRING_EMPTY, "A", -1 },
|
||||
new Object[] { STRING_L1, "a", 0 },
|
||||
new Object[] { STRING_L1, "A", 0 },
|
||||
new Object[] { STRING_L1, "\uFF21", -65248 },
|
||||
new Object[] { STRING_L1, "B", -1 },
|
||||
new Object[] { STRING_L2, "AB", 0 },
|
||||
new Object[] { STRING_L2, "aB", 0 },
|
||||
new Object[] { STRING_L2, "\uFF21", -65248 },
|
||||
new Object[] { STRING_L2, "A\uFF21", -65247 },
|
||||
new Object[] { STRING_L4, "ABCD", 0 },
|
||||
new Object[] { STRING_L4, "abcd", 0 },
|
||||
new Object[] { STRING_L4, "ABc\uFF21", -65245 },
|
||||
new Object[] { STRING_LLONG, "ABCDEFGH", 0 },
|
||||
new Object[] { STRING_LLONG, "abcdefgh", 0 },
|
||||
new Object[] { STRING_LLONG, "ABCDEFG\uFF21", -65241 },
|
||||
new Object[] { STRING_LLONG, "abcdefg\uFF21", -65241 },
|
||||
new Object[] { STRING_U1, "\uFF41", 0 },
|
||||
new Object[] { STRING_U1,
|
||||
"\uFF41\uFF42\uFF43\uFF44\uFF45\uFF46\uFF47\uFF48", -7 },
|
||||
new Object[] { STRING_U1, "A", 65248 },
|
||||
new Object[] { STRING_U2, "\uFF41", 1 },
|
||||
new Object[] { STRING_U2, "\uFF41\uFF42", 0 },
|
||||
new Object[] { STRING_U2,
|
||||
"\uFF41\uFF42\uFF43\uFF44\uFF45\uFF46\uFF47\uFF48", -6 },
|
||||
new Object[] { STRING_M12, "\uFF41a", 0 },
|
||||
new Object[] { STRING_M12, "\uFF41\uFF42", -65249 },
|
||||
new Object[] { STRING_M11, "a\uFF41", 0 },
|
||||
new Object[] { STRING_M11, "a\uFF42", -1 }, };
|
||||
}
|
||||
|
||||
@Test(dataProvider = "provider")
|
||||
public void testCompareToIgnoreCase(String str, String anotherString,
|
||||
int expected) {
|
||||
map.get(str)
|
||||
.forEach(
|
||||
(source, data) -> {
|
||||
assertEquals(
|
||||
data.compareToIgnoreCase(anotherString),
|
||||
expected,
|
||||
String.format(
|
||||
"testing String(%s).compareToIgnoreCase(%s), source : %s, ",
|
||||
escapeNonASCIIs(data),
|
||||
escapeNonASCIIs(anotherString),
|
||||
source));
|
||||
});
|
||||
}
|
||||
}
|
132
jdk/test/java/lang/String/CompactString/Concat.java
Normal file
132
jdk/test/java/lang/String/CompactString/Concat.java
Normal file
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8077559
|
||||
* @summary Tests Compact String. This one is for String.concat.
|
||||
* @run testng/othervm -XX:+CompactStrings Concat
|
||||
* @run testng/othervm -XX:-CompactStrings Concat
|
||||
*/
|
||||
|
||||
public class Concat extends CompactString {
|
||||
|
||||
@DataProvider
|
||||
public Object[][] provider() {
|
||||
return new Object[][] {
|
||||
new Object[] { STRING_EMPTY, "ABC", "ABC" },
|
||||
new Object[] { STRING_EMPTY,
|
||||
"ABC".concat("\uFF21\uFF22\uFF23").concat("DEF"),
|
||||
"ABC\uFF21\uFF22\uFF23DEF" },
|
||||
new Object[] {
|
||||
STRING_EMPTY,
|
||||
"\uFF21\uFF22\uFF23".concat("ABC").concat(
|
||||
"\uFF24\uFF25\uFF26"),
|
||||
"\uFF21\uFF22\uFF23ABC\uFF24\uFF25\uFF26" },
|
||||
new Object[] { STRING_L1,
|
||||
"ABC".concat("\uFF21\uFF22\uFF23").concat("DEF"),
|
||||
"AABC\uFF21\uFF22\uFF23DEF" },
|
||||
new Object[] {
|
||||
STRING_L1,
|
||||
"\uFF21\uFF22\uFF23".concat("ABC").concat(
|
||||
"\uFF24\uFF25\uFF26"),
|
||||
"A\uFF21\uFF22\uFF23ABC\uFF24\uFF25\uFF26" },
|
||||
new Object[] { STRING_L2,
|
||||
"ABC".concat("\uFF21\uFF22\uFF23").concat("DEF"),
|
||||
"ABABC\uFF21\uFF22\uFF23DEF" },
|
||||
new Object[] {
|
||||
STRING_L2,
|
||||
"\uFF21\uFF22\uFF23".concat("ABC").concat(
|
||||
"\uFF24\uFF25\uFF26"),
|
||||
"AB\uFF21\uFF22\uFF23ABC\uFF24\uFF25\uFF26" },
|
||||
new Object[] { STRING_L4,
|
||||
"ABC".concat("\uFF21\uFF22\uFF23").concat("DEF"),
|
||||
"ABCDABC\uFF21\uFF22\uFF23DEF" },
|
||||
new Object[] {
|
||||
STRING_L4,
|
||||
"\uFF21\uFF22\uFF23".concat("ABC").concat(
|
||||
"\uFF24\uFF25\uFF26"),
|
||||
"ABCD\uFF21\uFF22\uFF23ABC\uFF24\uFF25\uFF26" },
|
||||
new Object[] { STRING_LLONG,
|
||||
"ABC".concat("\uFF21\uFF22\uFF23").concat("DEF"),
|
||||
"ABCDEFGHABC\uFF21\uFF22\uFF23DEF" },
|
||||
new Object[] {
|
||||
STRING_LLONG,
|
||||
"\uFF21\uFF22\uFF23".concat("ABC").concat(
|
||||
"\uFF24\uFF25\uFF26"),
|
||||
"ABCDEFGH\uFF21\uFF22\uFF23ABC\uFF24\uFF25\uFF26" },
|
||||
new Object[] { STRING_U1,
|
||||
"ABC".concat("\uFF21\uFF22\uFF23").concat("DEF"),
|
||||
"\uFF21ABC\uFF21\uFF22\uFF23DEF" },
|
||||
new Object[] {
|
||||
STRING_U1,
|
||||
"\uFF21\uFF22\uFF23".concat("ABC").concat(
|
||||
"\uFF24\uFF25\uFF26"),
|
||||
"\uFF21\uFF21\uFF22\uFF23ABC\uFF24\uFF25\uFF26" },
|
||||
new Object[] { STRING_U2,
|
||||
"ABC".concat("\uFF21\uFF22\uFF23").concat("DEF"),
|
||||
"\uFF21\uFF22ABC\uFF21\uFF22\uFF23DEF" },
|
||||
new Object[] {
|
||||
STRING_U2,
|
||||
"\uFF21\uFF22\uFF23".concat("ABC").concat(
|
||||
"\uFF24\uFF25\uFF26"),
|
||||
"\uFF21\uFF22\uFF21\uFF22\uFF23ABC\uFF24\uFF25\uFF26" },
|
||||
new Object[] { STRING_M12,
|
||||
"ABC".concat("\uFF21\uFF22\uFF23").concat("DEF"),
|
||||
"\uFF21AABC\uFF21\uFF22\uFF23DEF" },
|
||||
new Object[] {
|
||||
STRING_M12,
|
||||
"\uFF21\uFF22\uFF23".concat("ABC").concat(
|
||||
"\uFF24\uFF25\uFF26"),
|
||||
"\uFF21A\uFF21\uFF22\uFF23ABC\uFF24\uFF25\uFF26" },
|
||||
new Object[] { STRING_M11,
|
||||
"ABC".concat("\uFF21\uFF22\uFF23").concat("DEF"),
|
||||
"A\uFF21ABC\uFF21\uFF22\uFF23DEF" },
|
||||
new Object[] {
|
||||
STRING_M11,
|
||||
"\uFF21\uFF22\uFF23".concat("ABC").concat(
|
||||
"\uFF24\uFF25\uFF26"),
|
||||
"A\uFF21\uFF21\uFF22\uFF23ABC\uFF24\uFF25\uFF26" }, };
|
||||
}
|
||||
|
||||
@Test(dataProvider = "provider")
|
||||
public void testConcat(String str, String anotherString, String expected) {
|
||||
map.get(str)
|
||||
.forEach(
|
||||
(source, data) -> {
|
||||
assertEquals(
|
||||
data.concat(anotherString),
|
||||
expected,
|
||||
String.format(
|
||||
"testing String(%s).concat(%s), source : %s, ",
|
||||
escapeNonASCIIs(data),
|
||||
escapeNonASCIIs(anotherString),
|
||||
source));
|
||||
});
|
||||
}
|
||||
}
|
91
jdk/test/java/lang/String/CompactString/Contains.java
Normal file
91
jdk/test/java/lang/String/CompactString/Contains.java
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8077559
|
||||
* @summary Tests Compact String. This one is for String.contains.
|
||||
* @run testng/othervm -XX:+CompactStrings Contains
|
||||
* @run testng/othervm -XX:-CompactStrings Contains
|
||||
*/
|
||||
|
||||
public class Contains extends CompactString {
|
||||
|
||||
@DataProvider
|
||||
public Object[][] provider() {
|
||||
return new Object[][] {
|
||||
|
||||
new Object[] { STRING_EMPTY, "", true },
|
||||
new Object[] { STRING_EMPTY, "A", false },
|
||||
new Object[] { STRING_EMPTY, "\uFF21", false },
|
||||
new Object[] { STRING_L1, "", true },
|
||||
new Object[] { STRING_L1, "A", true },
|
||||
new Object[] { STRING_L1, "\uFF21", false },
|
||||
new Object[] { STRING_L2, "", true },
|
||||
new Object[] { STRING_L2, "A", true },
|
||||
new Object[] { STRING_L2, "AB", true },
|
||||
new Object[] { STRING_L2, "B", true },
|
||||
new Object[] { STRING_L2, "ABC", false },
|
||||
new Object[] { STRING_L2, "ab", false },
|
||||
new Object[] { STRING_L4, "ABCD", true },
|
||||
new Object[] { STRING_L4, "BC", true },
|
||||
new Object[] { STRING_LLONG, "ABCDEFGH", true },
|
||||
new Object[] { STRING_LLONG, "BCDEFGH", true },
|
||||
new Object[] { STRING_LLONG, "EF", true },
|
||||
new Object[] { STRING_U1, "", true },
|
||||
new Object[] { STRING_U1, "\uFF21", true },
|
||||
new Object[] { STRING_U1, "a", false },
|
||||
new Object[] { STRING_U1, "\uFF21B", false },
|
||||
new Object[] { STRING_U2, "", true },
|
||||
new Object[] { STRING_U2, "\uFF21\uFF22", true },
|
||||
new Object[] { STRING_U2, "a", false },
|
||||
new Object[] { STRING_U2, "\uFF21B", false },
|
||||
new Object[] { STRING_M12, "\uFF21A", true },
|
||||
new Object[] { STRING_M12, "\uFF21", true },
|
||||
new Object[] { STRING_M12, "A", true },
|
||||
new Object[] { STRING_M12, "A\uFF21", false },
|
||||
new Object[] { STRING_M11, "A\uFF21", true },
|
||||
new Object[] { STRING_M11, "Ab", false }, };
|
||||
}
|
||||
|
||||
@Test(dataProvider = "provider")
|
||||
public void testContains(String str, String anotherString, boolean expected) {
|
||||
map.get(str)
|
||||
.forEach(
|
||||
(source, data) -> {
|
||||
assertEquals(
|
||||
data.contains(anotherString),
|
||||
expected,
|
||||
String.format(
|
||||
"testing String(%s).contains(%s), source : %s, ",
|
||||
escapeNonASCIIs(data),
|
||||
escapeNonASCIIs(anotherString),
|
||||
source));
|
||||
});
|
||||
}
|
||||
}
|
92
jdk/test/java/lang/String/CompactString/EndsWith.java
Normal file
92
jdk/test/java/lang/String/CompactString/EndsWith.java
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8077559
|
||||
* @summary Tests Compact String. This one is for String.endsWith.
|
||||
* @run testng/othervm -XX:+CompactStrings EndsWith
|
||||
* @run testng/othervm -XX:-CompactStrings EndsWith
|
||||
*/
|
||||
|
||||
public class EndsWith extends CompactString {
|
||||
|
||||
@DataProvider
|
||||
public Object[][] provider() {
|
||||
return new Object[][] { new Object[] { STRING_EMPTY, "", true },
|
||||
new Object[] { STRING_EMPTY, "A", false },
|
||||
new Object[] { STRING_L1, "A", true },
|
||||
new Object[] { STRING_L1, "", true },
|
||||
new Object[] { STRING_L1, " ", false },
|
||||
new Object[] { STRING_L2, "AB", true },
|
||||
new Object[] { STRING_L2, "B", true },
|
||||
new Object[] { STRING_L2, "", true },
|
||||
new Object[] { STRING_L2, "A", false },
|
||||
new Object[] { STRING_L4, "ABCD", true },
|
||||
new Object[] { STRING_L4, "CD", true },
|
||||
new Object[] { STRING_L4, "D", true },
|
||||
new Object[] { STRING_L4, "", true },
|
||||
new Object[] { STRING_L4, "BC", false },
|
||||
new Object[] { STRING_LLONG, "ABCDEFGH", true },
|
||||
new Object[] { STRING_LLONG, "EFGH", true },
|
||||
new Object[] { STRING_LLONG, "", true },
|
||||
new Object[] { STRING_LLONG, "CDEF", false },
|
||||
new Object[] { STRING_LLONG, "\uFF28", false },
|
||||
new Object[] { STRING_U1, "\uFF21", true },
|
||||
new Object[] { STRING_U1, "", true },
|
||||
new Object[] { STRING_U1, "\uFF22", false },
|
||||
new Object[] { STRING_U1, "B", false },
|
||||
new Object[] { STRING_U2, "\uFF21\uFF22", true },
|
||||
new Object[] { STRING_U2, "\uFF22", true },
|
||||
new Object[] { STRING_U2, "", true },
|
||||
new Object[] { STRING_U2, "\uFF21", false },
|
||||
new Object[] { STRING_M12, "\uFF21A", true },
|
||||
new Object[] { STRING_M12, "A", true },
|
||||
new Object[] { STRING_M12, "", true },
|
||||
new Object[] { STRING_M12, "AA", false },
|
||||
new Object[] { STRING_M11, "A\uFF21", true },
|
||||
new Object[] { STRING_M11, "\uFF21", true },
|
||||
new Object[] { STRING_M11, "", true },
|
||||
new Object[] { STRING_M11, "\uFF21\uFF21", false }, };
|
||||
}
|
||||
|
||||
@Test(dataProvider = "provider")
|
||||
public void testEndsWith(String str, String suffix, boolean expected) {
|
||||
map.get(str)
|
||||
.forEach(
|
||||
(source, data) -> {
|
||||
assertEquals(
|
||||
data.endsWith(suffix),
|
||||
expected,
|
||||
String.format(
|
||||
"testing String(%s).endsWith(%s), source : %s, ",
|
||||
escapeNonASCIIs(data),
|
||||
escapeNonASCIIs(suffix), source));
|
||||
});
|
||||
}
|
||||
}
|
81
jdk/test/java/lang/String/CompactString/Equals.java
Normal file
81
jdk/test/java/lang/String/CompactString/Equals.java
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8077559
|
||||
* @summary Tests Compact String. This one is for String.equals.
|
||||
* @run testng/othervm -XX:+CompactStrings Equals
|
||||
* @run testng/othervm -XX:-CompactStrings Equals
|
||||
*/
|
||||
|
||||
public class Equals extends CompactString {
|
||||
|
||||
@DataProvider
|
||||
public Object[][] provider() {
|
||||
return new Object[][] {
|
||||
new Object[] { STRING_EMPTY, "", true },
|
||||
new Object[] { STRING_EMPTY, "A", false },
|
||||
new Object[] { STRING_EMPTY, new StringBuffer(""), false },
|
||||
new Object[] { STRING_L1, "A", true },
|
||||
new Object[] { STRING_L1, "", false },
|
||||
new Object[] { STRING_L1, new StringBuffer("A"), false },
|
||||
new Object[] { STRING_L2, "AB", true },
|
||||
new Object[] { STRING_L2, "", false },
|
||||
new Object[] { STRING_L2, new StringBuilder("AB"), false },
|
||||
new Object[] { STRING_L4, "ABCD", true },
|
||||
new Object[] { STRING_L4, "abc", false },
|
||||
new Object[] { STRING_L4, "", false },
|
||||
new Object[] { STRING_LLONG, "ABCDEFGH", true },
|
||||
new Object[] { STRING_LLONG, "ABCDEFG", false },
|
||||
new Object[] { STRING_LLONG, new StringBuilder("ABCDEFGH"),
|
||||
false },
|
||||
new Object[] { STRING_U1, "\uFF21", true },
|
||||
new Object[] { STRING_U1, "", false },
|
||||
new Object[] { STRING_U2, "\uFF21\uFF22", true },
|
||||
new Object[] { STRING_U2, "\uFF21", false },
|
||||
new Object[] { STRING_U2, "", false },
|
||||
new Object[] { STRING_U2, new StringBuilder("\uFF21\uFF22"),
|
||||
false },
|
||||
new Object[] { STRING_M12, "\uFF21A", true },
|
||||
new Object[] { STRING_M12, "A\uFF21", false },
|
||||
new Object[] { STRING_M11, "A\uFF21", true },
|
||||
new Object[] { STRING_M11, new StringBuilder("\uFF21A"), false }, };
|
||||
}
|
||||
|
||||
@Test(dataProvider = "provider")
|
||||
public void testEquals(String str, Object obj, boolean expected) {
|
||||
map.get(str).forEach(
|
||||
(source, data) -> {
|
||||
assertEquals(data.equals(obj), expected, String.format(
|
||||
"testing String(%s).equals(%s), source : %s, ",
|
||||
escapeNonASCIIs(data),
|
||||
escapeNonASCIIs(obj.toString()), source));
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8077559
|
||||
* @summary Tests Compact String. This one is for String.equalsIgnoreCase.
|
||||
* @run testng/othervm -XX:+CompactStrings EqualsIgnoreCase
|
||||
* @run testng/othervm -XX:-CompactStrings EqualsIgnoreCase
|
||||
*/
|
||||
|
||||
public class EqualsIgnoreCase extends CompactString {
|
||||
|
||||
@DataProvider
|
||||
public Object[][] provider() {
|
||||
return new Object[][] {
|
||||
|
||||
new Object[] { STRING_EMPTY, "", true },
|
||||
new Object[] { STRING_L1, "a", true },
|
||||
new Object[] { STRING_L2, "aB", true },
|
||||
new Object[] { STRING_L4, "AbCd", true },
|
||||
new Object[] { STRING_LLONG, "aBcDeFgH", true },
|
||||
new Object[] { STRING_U1, "\uFF41", true },
|
||||
new Object[] { STRING_U1, "\uFF21", true },
|
||||
new Object[] { STRING_U2, "\uFF41\uFF42", true },
|
||||
new Object[] { STRING_U2, "\uFF41\uFF22", true },
|
||||
new Object[] { STRING_U2, "\uFF21\uFF42", true },
|
||||
new Object[] { STRING_M12, "\uFF41a", true },
|
||||
new Object[] { STRING_M12, "\uFF21A", true },
|
||||
new Object[] { STRING_M11, "a\uFF41", true },
|
||||
new Object[] { STRING_M11, "A\uFF21", true },
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@Test(dataProvider = "provider")
|
||||
public void testEqualsIgnoreCase(String str, String anotherString,
|
||||
boolean expected) {
|
||||
map.get(str)
|
||||
.forEach(
|
||||
(source, data) -> {
|
||||
assertEquals(
|
||||
data.equalsIgnoreCase(anotherString),
|
||||
expected,
|
||||
String.format(
|
||||
"testing String(%s).equalsIgnoreCase(%s), source : %s, ",
|
||||
escapeNonASCIIs(data),
|
||||
escapeNonASCIIs(anotherString),
|
||||
source));
|
||||
});
|
||||
}
|
||||
}
|
91
jdk/test/java/lang/String/CompactString/GetChars.java
Normal file
91
jdk/test/java/lang/String/CompactString/GetChars.java
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8077559
|
||||
* @summary Tests Compact String. This one is for String.getChars.
|
||||
* @run testng/othervm -XX:+CompactStrings GetChars
|
||||
* @run testng/othervm -XX:-CompactStrings GetChars
|
||||
*/
|
||||
|
||||
public class GetChars extends CompactString {
|
||||
|
||||
@DataProvider
|
||||
public Object[][] provider() {
|
||||
return new Object[][] {
|
||||
|
||||
new Object[] { STRING_EMPTY, 0, STRING_EMPTY.length(),
|
||||
new char[STRING_EMPTY.length()], 0, CHAR_ARRAY_EMPTY },
|
||||
new Object[] { STRING_L1, 0, STRING_L1.length(),
|
||||
new char[STRING_L1.length()], 0, CHAR_ARRAY_L1 },
|
||||
new Object[] { STRING_L2, 0, STRING_L2.length(),
|
||||
new char[STRING_L2.length()], 0, CHAR_ARRAY_L2 },
|
||||
new Object[] { STRING_L4, 0, STRING_L4.length(),
|
||||
new char[STRING_L4.length()], 0, CHAR_ARRAY_L4 },
|
||||
new Object[] { STRING_LLONG, 0, STRING_LLONG.length(),
|
||||
new char[STRING_LLONG.length()], 0, CHAR_ARRAY_LLONG },
|
||||
new Object[] { STRING_U1, 0, STRING_U1.length(),
|
||||
new char[STRING_U1.length()], 0, CHAR_ARRAY_U1 },
|
||||
new Object[] { STRING_U2, 0, STRING_U2.length(),
|
||||
new char[STRING_U2.length()], 0, CHAR_ARRAY_U2 },
|
||||
new Object[] { STRING_M12, 0, STRING_M12.length(),
|
||||
new char[STRING_M12.length()], 0, CHAR_ARRAY_M12 },
|
||||
new Object[] { STRING_M11, 0, STRING_M11.length(),
|
||||
new char[STRING_M11.length()], 0, CHAR_ARRAY_M11 },
|
||||
new Object[] { STRING_UDUPLICATE, 0,
|
||||
STRING_UDUPLICATE.length(),
|
||||
new char[STRING_UDUPLICATE.length()], 0,
|
||||
CHAR_ARRAY_UDUPLICATE },
|
||||
new Object[] { STRING_MDUPLICATE1, 0,
|
||||
STRING_MDUPLICATE1.length(),
|
||||
new char[STRING_MDUPLICATE1.length()], 0,
|
||||
CHAR_ARRAY_MDUPLICATE1 }, };
|
||||
}
|
||||
|
||||
@Test(dataProvider = "provider")
|
||||
public void testGetChars(String str, int srcBegin, int srcEnd, char[] dst,
|
||||
int dstBegin, char[] expected) {
|
||||
map.get(str)
|
||||
.forEach(
|
||||
(source, data) -> {
|
||||
data.getChars(srcBegin, srcEnd, dst, dstBegin);
|
||||
assertTrue(
|
||||
Arrays.equals(dst, expected),
|
||||
String.format(
|
||||
"testing String(%s).getChars(%d, %d, %s, %d), source : %s, ",
|
||||
escapeNonASCIIs(data), srcBegin,
|
||||
srcEnd, escapeNonASCIIs(Arrays
|
||||
.toString(dst)), dstBegin,
|
||||
source));
|
||||
});
|
||||
}
|
||||
|
||||
}
|
249
jdk/test/java/lang/String/CompactString/IndexOf.java
Normal file
249
jdk/test/java/lang/String/CompactString/IndexOf.java
Normal file
@ -0,0 +1,249 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8077559
|
||||
* @summary Tests Compact String. This one is for String.indexOf.
|
||||
* @run testng/othervm -XX:+CompactStrings IndexOf
|
||||
* @run testng/othervm -XX:-CompactStrings IndexOf
|
||||
*/
|
||||
|
||||
public class IndexOf extends CompactString {
|
||||
|
||||
@DataProvider
|
||||
public Object[][] provider() {
|
||||
return new Object[][] {
|
||||
|
||||
new Object[] { STRING_EMPTY, (int) 'A', -1 },
|
||||
new Object[] { STRING_L1, (int) 'A', 0 },
|
||||
new Object[] { STRING_L2, (int) 'A', 0 },
|
||||
new Object[] { STRING_L2, (int) 'B', 1 },
|
||||
new Object[] { STRING_L4, (int) 'A', 0 },
|
||||
new Object[] { STRING_L4, (int) 'D', 3 },
|
||||
new Object[] { STRING_L4, (int) 'E', -1 },
|
||||
new Object[] { STRING_LLONG, (int) 'A', 0 },
|
||||
new Object[] { STRING_LLONG, (int) 'H', 7 },
|
||||
new Object[] { STRING_U1, (int) '\uFF21', 0 },
|
||||
new Object[] { STRING_U1, (int) 'A', -1 },
|
||||
new Object[] { STRING_U2, (int) '\uFF21', 0 },
|
||||
new Object[] { STRING_U2, (int) '\uFF22', 1 },
|
||||
new Object[] { STRING_M12, (int) '\uFF21', 0 },
|
||||
new Object[] { STRING_M12, (int) 'A', 1 },
|
||||
new Object[] { STRING_M11, (int) 'A', 0 },
|
||||
new Object[] { STRING_M11, (int) '\uFF21', 1 },
|
||||
new Object[] { STRING_UDUPLICATE, (int) '\uFF21', 0 },
|
||||
new Object[] { STRING_UDUPLICATE, (int) '\uFF22', 1 },
|
||||
new Object[] { STRING_SUPPLEMENTARY, 'A', 5 },
|
||||
new Object[] { STRING_SUPPLEMENTARY, '\uFF21', 4 },
|
||||
new Object[] { STRING_SUPPLEMENTARY,
|
||||
Character.toCodePoint('\uD801', '\uDC00'), 0 },
|
||||
new Object[] { STRING_SUPPLEMENTARY,
|
||||
Character.toCodePoint('\uD801', '\uDC01'), 2 }, };
|
||||
}
|
||||
|
||||
@Test(dataProvider = "provider")
|
||||
public void testIndexOf(String str, int ch, int expected) {
|
||||
map.get(str).forEach(
|
||||
(source, data) -> {
|
||||
assertEquals(data.indexOf(ch), expected, String.format(
|
||||
"testing String(%s).indexOf(%d), source : %s, ",
|
||||
escapeNonASCIIs(data), ch, source));
|
||||
});
|
||||
}
|
||||
|
||||
@DataProvider
|
||||
public Object[][] provider2() {
|
||||
return new Object[][] {
|
||||
|
||||
new Object[] { STRING_EMPTY, (int) 'A', 0, -1 },
|
||||
new Object[] { STRING_L1, (int) 'A', 0, 0 },
|
||||
new Object[] { STRING_L1, (int) 'A', 1, -1 },
|
||||
new Object[] { STRING_L1, (int) 'B', 0, -1 },
|
||||
new Object[] { STRING_L2, (int) 'A', 0, 0 },
|
||||
new Object[] { STRING_L2, (int) 'A', 1, -1 },
|
||||
new Object[] { STRING_L2, (int) 'B', 0, 1 },
|
||||
new Object[] { STRING_L2, (int) 'B', 1, 1 },
|
||||
new Object[] { STRING_L4, (int) 'A', 0, 0 },
|
||||
new Object[] { STRING_L4, (int) 'D', 2, 3 },
|
||||
new Object[] { STRING_L4, (int) 'B', 2, -1 },
|
||||
new Object[] { STRING_LLONG, (int) 'A', 0, 0 },
|
||||
new Object[] { STRING_LLONG, (int) 'H', 5, 7 },
|
||||
new Object[] { STRING_U1, (int) '\uFF21', 0, 0 },
|
||||
new Object[] { STRING_U1, (int) 'A', 0, -1 },
|
||||
new Object[] { STRING_U2, (int) '\uFF21', 0, 0 },
|
||||
new Object[] { STRING_U2, (int) '\uFF22', 0, 1 },
|
||||
new Object[] { STRING_M12, (int) '\uFF21', 0, 0 },
|
||||
new Object[] { STRING_M12, (int) 'A', 1, 1 },
|
||||
new Object[] { STRING_M11, (int) 'A', 0, 0 },
|
||||
new Object[] { STRING_M11, (int) '\uFF21', 1, 1 },
|
||||
new Object[] { STRING_UDUPLICATE, (int) '\uFF21', 1, 2 },
|
||||
new Object[] { STRING_UDUPLICATE, (int) '\uFF22', 1, 1 }, };
|
||||
}
|
||||
|
||||
@Test(dataProvider = "provider2")
|
||||
public void testIndexOf(String str, int ch, int fromIndex, int expected) {
|
||||
map.get(str)
|
||||
.forEach(
|
||||
(source, data) -> {
|
||||
assertEquals(
|
||||
data.indexOf(ch, fromIndex),
|
||||
expected,
|
||||
String.format(
|
||||
"testing String(%s).indexOf(%d, %d), source : %s, ",
|
||||
escapeNonASCIIs(data), ch,
|
||||
fromIndex, source));
|
||||
});
|
||||
}
|
||||
|
||||
@DataProvider
|
||||
public Object[][] provider3() {
|
||||
return new Object[][] {
|
||||
|
||||
new Object[] { STRING_EMPTY, "A", -1 },
|
||||
new Object[] { STRING_L1, "A", 0 },
|
||||
new Object[] { STRING_L1, "AB", -1 },
|
||||
new Object[] { STRING_L2, "A", 0 },
|
||||
new Object[] { STRING_L2, "B", 1 },
|
||||
new Object[] { STRING_L2, "AB", 0 },
|
||||
new Object[] { STRING_L2, "AC", -1 },
|
||||
new Object[] { STRING_L2, "ABC", -1 },
|
||||
new Object[] { STRING_L4, "ABCD", 0 },
|
||||
new Object[] { STRING_L4, "D", 3 },
|
||||
new Object[] { STRING_LLONG, "ABCDEFGH", 0 },
|
||||
new Object[] { STRING_LLONG, "EFGH", 4 },
|
||||
new Object[] { STRING_LLONG, "EFGHI", -1 },
|
||||
new Object[] { STRING_U1, "\uFF21", 0 },
|
||||
new Object[] { STRING_U1, "\uFF21A", -1 },
|
||||
new Object[] { STRING_U2, "\uFF21\uFF22", 0 },
|
||||
new Object[] { STRING_U2, "\uFF22", 1 },
|
||||
new Object[] { STRING_U2, "A\uFF22", -1 },
|
||||
new Object[] { STRING_M12, "\uFF21A", 0 },
|
||||
new Object[] { STRING_M12, "A", 1 },
|
||||
new Object[] { STRING_M12, "\uFF21\uFF21", -1 },
|
||||
new Object[] { STRING_M11, "A\uFF21", 0 },
|
||||
new Object[] { STRING_M11, "\uFF21", 1 },
|
||||
new Object[] { STRING_M11, "A", 0 },
|
||||
new Object[] {
|
||||
STRING_UDUPLICATE,
|
||||
"\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22",
|
||||
0 },
|
||||
new Object[] { STRING_UDUPLICATE,
|
||||
"\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21", 1 },
|
||||
new Object[] {
|
||||
STRING_UDUPLICATE,
|
||||
"\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21",
|
||||
-1 }, };
|
||||
}
|
||||
|
||||
@Test(dataProvider = "provider3")
|
||||
public void testIndexOf(String str, String anotherString, int expected) {
|
||||
map.get(str)
|
||||
.forEach(
|
||||
(source, data) -> {
|
||||
assertEquals(
|
||||
data.indexOf(anotherString),
|
||||
expected,
|
||||
String.format(
|
||||
"testing String(%s).indexOf(%s), source : %s, ",
|
||||
escapeNonASCIIs(data),
|
||||
escapeNonASCIIs(anotherString),
|
||||
source));
|
||||
});
|
||||
}
|
||||
|
||||
@DataProvider
|
||||
public Object[][] provider4() {
|
||||
return new Object[][] {
|
||||
|
||||
new Object[] { STRING_EMPTY, "A", 0, -1 },
|
||||
new Object[] { STRING_L1, "A", 0, 0 },
|
||||
new Object[] { STRING_L1, "A", 1, -1 },
|
||||
new Object[] { STRING_L1, "AB", 0, -1 },
|
||||
new Object[] { STRING_L2, "A", 0, 0 },
|
||||
new Object[] { STRING_L2, "B", 0, 1 },
|
||||
new Object[] { STRING_L2, "AB", 0, 0 },
|
||||
new Object[] { STRING_L2, "AB", 1, -1 },
|
||||
new Object[] { STRING_L4, "ABCD", 0, 0 },
|
||||
new Object[] { STRING_L4, "BC", 0, 1 },
|
||||
new Object[] { STRING_L4, "A", 0, 0 },
|
||||
new Object[] { STRING_L4, "CD", 0, 2 },
|
||||
new Object[] { STRING_L4, "A", 2, -1 },
|
||||
new Object[] { STRING_L4, "ABCDE", 0, -1 },
|
||||
new Object[] { STRING_LLONG, "ABCDEFGH", 0, 0 },
|
||||
new Object[] { STRING_LLONG, "DEFGH", 0, 3 },
|
||||
new Object[] { STRING_LLONG, "A", 0, 0 },
|
||||
new Object[] { STRING_LLONG, "GHI", 0, -1 },
|
||||
new Object[] { STRING_U1, "\uFF21", 0, 0 },
|
||||
new Object[] { STRING_U1, "\uFF21A", 0, -1 },
|
||||
new Object[] { STRING_U2, "\uFF21\uFF22", 0, 0 },
|
||||
new Object[] { STRING_U2, "\uFF22", 0, 1 },
|
||||
new Object[] { STRING_U2, "\uFF21", 1, -1 },
|
||||
new Object[] { STRING_M12, "\uFF21A", 0, 0 },
|
||||
new Object[] { STRING_M12, "A", 1, 1 },
|
||||
new Object[] { STRING_M12, "\uFF21A", 1, -1 },
|
||||
new Object[] { STRING_M12, "\uFF21", 0, 0 },
|
||||
new Object[] { STRING_M11, "A\uFF21", 0, 0 },
|
||||
new Object[] { STRING_M11, "\uFF21", 1, 1 },
|
||||
new Object[] { STRING_M11, "A\uFF21", 1, -1 },
|
||||
new Object[] { STRING_M11, "A\uFF21A", 0, -1 },
|
||||
new Object[] {
|
||||
STRING_UDUPLICATE,
|
||||
"\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22",
|
||||
0, 0 },
|
||||
new Object[] {
|
||||
STRING_UDUPLICATE,
|
||||
"\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22",
|
||||
1, -1 },
|
||||
new Object[] {
|
||||
STRING_UDUPLICATE,
|
||||
"\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22",
|
||||
1, 1 },
|
||||
new Object[] { STRING_UDUPLICATE, "\uFF21\uFF22\uFF21\uFF22",
|
||||
4, 4 },
|
||||
new Object[] { STRING_UDUPLICATE, "\uFF21\uFF22\uFF21\uFF22",
|
||||
7, -1 }, };
|
||||
}
|
||||
|
||||
@Test(dataProvider = "provider4")
|
||||
public void testIndexOf(String str, String anotherString, int fromIndex,
|
||||
int expected) {
|
||||
map.get(str)
|
||||
.forEach(
|
||||
(source, data) -> {
|
||||
assertEquals(
|
||||
data.indexOf(anotherString, fromIndex),
|
||||
expected,
|
||||
String.format(
|
||||
"testing String(%s).indexOf(%s), source : %s, ",
|
||||
escapeNonASCIIs(data),
|
||||
escapeNonASCIIs(anotherString),
|
||||
fromIndex, source));
|
||||
});
|
||||
}
|
||||
}
|
64
jdk/test/java/lang/String/CompactString/Intern.java
Normal file
64
jdk/test/java/lang/String/CompactString/Intern.java
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8077559
|
||||
* @summary Tests Compact String. This one is for String.intern.
|
||||
* @run testng/othervm -XX:+CompactStrings Intern
|
||||
* @run testng/othervm -XX:-CompactStrings Intern
|
||||
*/
|
||||
|
||||
public class Intern extends CompactString {
|
||||
|
||||
@DataProvider
|
||||
public Object[][] provider() {
|
||||
return new Object[][] {
|
||||
|
||||
new Object[] { STRING_EMPTY, "" },
|
||||
new Object[] { STRING_L1, "A" },
|
||||
new Object[] { STRING_LLONG, "ABCDEFGH" },
|
||||
new Object[] { STRING_U1, "\uFF21" },
|
||||
new Object[] { STRING_U2, "\uFF21\uFF22" },
|
||||
new Object[] { STRING_M12, "\uFF21A" },
|
||||
new Object[] { STRING_M11, "A\uFF21" },
|
||||
new Object[] { STRING_MDUPLICATE1,
|
||||
"\uFF21A\uFF21A\uFF21A\uFF21A\uFF21A" }, };
|
||||
}
|
||||
|
||||
@Test(dataProvider = "provider")
|
||||
public void testIntern(String str, String expected) {
|
||||
map.get(str).forEach(
|
||||
(source, data) -> {
|
||||
assertTrue(data.intern() == expected, String.format(
|
||||
"testing String(%s).intern(), source : %s, ",
|
||||
escapeNonASCIIs(data), source));
|
||||
});
|
||||
}
|
||||
}
|
225
jdk/test/java/lang/String/CompactString/LastIndexOf.java
Normal file
225
jdk/test/java/lang/String/CompactString/LastIndexOf.java
Normal file
@ -0,0 +1,225 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8077559
|
||||
* @summary Tests Compact String. This one is for String.lastIndexOf.
|
||||
* @run testng/othervm -XX:+CompactStrings LastIndexOf
|
||||
* @run testng/othervm -XX:-CompactStrings LastIndexOf
|
||||
*/
|
||||
|
||||
public class LastIndexOf extends CompactString {
|
||||
|
||||
@DataProvider
|
||||
public Object[][] provider() {
|
||||
return new Object[][] {
|
||||
|
||||
new Object[] { STRING_EMPTY, (int) 'A', -1 },
|
||||
new Object[] { STRING_L1, (int) 'A', 0 },
|
||||
new Object[] { STRING_L2, (int) 'A', 0 },
|
||||
new Object[] { STRING_L2, (int) 'B', 1 },
|
||||
new Object[] { STRING_L4, (int) 'A', 0 },
|
||||
new Object[] { STRING_L4, (int) 'D', 3 },
|
||||
new Object[] { STRING_LLONG, (int) 'A', 0 },
|
||||
new Object[] { STRING_LLONG, (int) 'H', 7 },
|
||||
new Object[] { STRING_U1, (int) '\uFF21', 0 },
|
||||
new Object[] { STRING_U1, (int) 'B', -1 },
|
||||
new Object[] { STRING_U2, (int) '\uFF21', 0 },
|
||||
new Object[] { STRING_U2, (int) '\uFF22', 1 },
|
||||
new Object[] { STRING_M12, (int) '\uFF21', 0 },
|
||||
new Object[] { STRING_M12, (int) 'A', 1 },
|
||||
new Object[] { STRING_M11, (int) 'A', 0 },
|
||||
new Object[] { STRING_M11, (int) '\uFF21', 1 },
|
||||
new Object[] { STRING_UDUPLICATE, (int) '\uFF22', 9 },
|
||||
new Object[] { STRING_UDUPLICATE, (int) '\uFF21', 8 },
|
||||
new Object[] { STRING_SUPPLEMENTARY,
|
||||
Character.toCodePoint('\uD801', '\uDC01'), 2 }, };
|
||||
}
|
||||
|
||||
@Test(dataProvider = "provider")
|
||||
public void testLastIndexOf(String str, int ch, int expected) {
|
||||
map.get(str)
|
||||
.forEach(
|
||||
(source, data) -> {
|
||||
assertEquals(
|
||||
data.lastIndexOf(ch),
|
||||
expected,
|
||||
String.format(
|
||||
"testing String(%s).lastIndexOf(%d), source : %s, ",
|
||||
escapeNonASCIIs(data), ch, source));
|
||||
});
|
||||
}
|
||||
|
||||
@DataProvider
|
||||
public Object[][] provider2() {
|
||||
return new Object[][] {
|
||||
|
||||
new Object[] { STRING_EMPTY, (int) 'A', 0, -1 },
|
||||
new Object[] { STRING_L1, (int) 'A', 0, 0 },
|
||||
new Object[] { STRING_L1, (int) 'A', 1, 0 },
|
||||
new Object[] { STRING_L2, (int) 'A', 0, 0 },
|
||||
new Object[] { STRING_L2, (int) 'B', 1, 1 },
|
||||
new Object[] { STRING_L2, (int) 'B', 2, 1 },
|
||||
new Object[] { STRING_L4, (int) 'A', 0, 0 },
|
||||
new Object[] { STRING_L4, (int) 'C', 2, 2 },
|
||||
new Object[] { STRING_L4, (int) 'C', 1, -1 },
|
||||
new Object[] { STRING_LLONG, (int) 'A', 0, 0 },
|
||||
new Object[] { STRING_LLONG, (int) 'H', 7, 7 },
|
||||
new Object[] { STRING_LLONG, (int) 'H', 6, -1 },
|
||||
new Object[] { STRING_U1, (int) '\uFF21', 0, 0 },
|
||||
new Object[] { STRING_U1, (int) '\uFF21', 7, 0 },
|
||||
new Object[] { STRING_U2, (int) '\uFF21', 0, 0 },
|
||||
new Object[] { STRING_U2, (int) '\uFF22', 0, -1 },
|
||||
new Object[] { STRING_M12, (int) '\uFF21', 0, 0 },
|
||||
new Object[] { STRING_M12, (int) 'A', 1, 1 },
|
||||
new Object[] { STRING_M12, (int) 'A', 0, -1 },
|
||||
new Object[] { STRING_M11, (int) 'A', 0, 0 },
|
||||
new Object[] { STRING_M11, (int) '\uFF21', 1, 1 },
|
||||
new Object[] { STRING_M11, (int) '\uFF21', 0, -1 },
|
||||
new Object[] { STRING_UDUPLICATE, (int) '\uFF21', 5, 4 },
|
||||
new Object[] { STRING_UDUPLICATE, (int) '\uFF21', 6, 6 },
|
||||
new Object[] { STRING_UDUPLICATE, (int) '\uFF22', 5, 5 },
|
||||
new Object[] { STRING_UDUPLICATE, (int) '\uFF22', 6, 5 }, };
|
||||
}
|
||||
|
||||
@Test(dataProvider = "provider2")
|
||||
public void testLastIndexOf(String str, int ch, int fromIndex, int expected) {
|
||||
map.get(str)
|
||||
.forEach(
|
||||
(source, data) -> {
|
||||
assertEquals(
|
||||
data.lastIndexOf(ch, fromIndex),
|
||||
expected,
|
||||
String.format(
|
||||
"testing String(%s).lastIndexOf(%d, %d), source : %s, ",
|
||||
escapeNonASCIIs(data), ch,
|
||||
fromIndex, source));
|
||||
});
|
||||
}
|
||||
|
||||
@DataProvider
|
||||
public Object[][] provider3() {
|
||||
return new Object[][] {
|
||||
|
||||
new Object[] { STRING_EMPTY, "A", -1 },
|
||||
new Object[] { STRING_L1, "A", 0 },
|
||||
new Object[] { STRING_L1, "AB", -1 },
|
||||
|
||||
new Object[] { STRING_L2, "AB", 0 },
|
||||
new Object[] { STRING_L2, "B", 1 },
|
||||
new Object[] { STRING_L4, "ABCD", 0 },
|
||||
new Object[] { STRING_L4, "B", 1 },
|
||||
new Object[] { STRING_LLONG, "ABCD", 0 },
|
||||
new Object[] { STRING_LLONG, "GH", 6 },
|
||||
new Object[] { STRING_U1, "\uFF21", 0 },
|
||||
new Object[] { STRING_U1, "\uFF22", -1 },
|
||||
new Object[] { STRING_U2, "\uFF21\uFF22", 0 },
|
||||
new Object[] { STRING_U2, "\uFF22", 1 },
|
||||
new Object[] { STRING_M12, "\uFF21A", 0 },
|
||||
new Object[] { STRING_M12, "A", 1 },
|
||||
new Object[] { STRING_M11, "A\uFF21", 0 },
|
||||
new Object[] { STRING_M11, "\uFF21", 1 },
|
||||
new Object[] { STRING_UDUPLICATE, "\uFF21\uFF22\uFF21\uFF22", 6 },
|
||||
new Object[] { STRING_UDUPLICATE, "\uFF21\uFF22", 8 }, };
|
||||
}
|
||||
|
||||
@Test(dataProvider = "provider3")
|
||||
public void testLastIndexOf(String str, String anotherString, int expected) {
|
||||
map.get(str)
|
||||
.forEach(
|
||||
(source, data) -> {
|
||||
assertEquals(
|
||||
data.lastIndexOf(anotherString),
|
||||
expected,
|
||||
String.format(
|
||||
"testing String(%s).lastIndexOf(%s), source : %s, ",
|
||||
escapeNonASCIIs(data),
|
||||
escapeNonASCIIs(anotherString),
|
||||
source));
|
||||
});
|
||||
}
|
||||
|
||||
@DataProvider
|
||||
public Object[][] provider4() {
|
||||
return new Object[][] {
|
||||
|
||||
new Object[] { STRING_EMPTY, "A", 0, -1 },
|
||||
new Object[] { STRING_L2, "AB", 0, 0 },
|
||||
|
||||
new Object[] { STRING_L1, "AB", -1, -1 },
|
||||
|
||||
new Object[] { STRING_L2, "B", 1, 1 },
|
||||
new Object[] { STRING_L2, "B", 0, -1 },
|
||||
new Object[] { STRING_L4, "ABC", 3, 0 },
|
||||
new Object[] { STRING_L4, "ABC", 0, 0 },
|
||||
new Object[] { STRING_L4, "ABC", 1, 0 },
|
||||
new Object[] { STRING_L4, "BC", 1, 1 },
|
||||
new Object[] { STRING_L4, "BC", 0, -1 },
|
||||
new Object[] { STRING_LLONG, "ABCDEFGH", 0, 0 },
|
||||
new Object[] { STRING_LLONG, "EFGH", 7, 4 },
|
||||
new Object[] { STRING_LLONG, "EFGH", 3, -1 },
|
||||
new Object[] { STRING_U1, "\uFF21", 0, 0 },
|
||||
new Object[] { STRING_U1, "\uFF21", 7, 0 },
|
||||
new Object[] { STRING_U2, "\uFF21\uFF22", 0, 0 },
|
||||
new Object[] { STRING_U2, "\uFF21\uFF22", 1, 0 },
|
||||
new Object[] { STRING_M12, "\uFF21A", 0, 0 },
|
||||
new Object[] { STRING_M12, "A", 1, 1 },
|
||||
new Object[] { STRING_M12, "A", 0, -1 },
|
||||
new Object[] { STRING_M11, "A\uFF21", 0, 0 },
|
||||
new Object[] { STRING_M11, "A\uFF21", 1, 0 },
|
||||
new Object[] { STRING_M11, "\uFF21", 0, -1 },
|
||||
new Object[] {
|
||||
STRING_UDUPLICATE,
|
||||
"\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22",
|
||||
9, 0 },
|
||||
new Object[] {
|
||||
STRING_UDUPLICATE,
|
||||
"\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22",
|
||||
0, 0 },
|
||||
new Object[] { STRING_UDUPLICATE, "\uFF21\uFF22", 6, 6 },
|
||||
new Object[] { STRING_UDUPLICATE, "\uFF21\uFF22\uFF21", 6, 6 }, };
|
||||
}
|
||||
|
||||
@Test(dataProvider = "provider4")
|
||||
public void testLastIndexOf(String str, String anotherString,
|
||||
int fromIndex, int expected) {
|
||||
map.get(str)
|
||||
.forEach(
|
||||
(source, data) -> {
|
||||
assertEquals(
|
||||
data.lastIndexOf(anotherString, fromIndex),
|
||||
expected,
|
||||
String.format(
|
||||
"testing String(%s).lastIndexOf(%s, %d), source : %s, ",
|
||||
escapeNonASCIIs(data),
|
||||
escapeNonASCIIs(anotherString),
|
||||
fromIndex, source));
|
||||
});
|
||||
}
|
||||
}
|
61
jdk/test/java/lang/String/CompactString/Length.java
Normal file
61
jdk/test/java/lang/String/CompactString/Length.java
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8077559
|
||||
* @summary Tests Compact String. This one is for String.length.
|
||||
* @run testng/othervm -XX:+CompactStrings Length
|
||||
* @run testng/othervm -XX:-CompactStrings Length
|
||||
*/
|
||||
|
||||
public class Length extends CompactString {
|
||||
|
||||
@DataProvider
|
||||
public Object[][] provider() {
|
||||
return new Object[][] {
|
||||
|
||||
new Object[] { STRING_EMPTY, 0 }, new Object[] { STRING_L1, 1 },
|
||||
new Object[] { STRING_L2, 2 },
|
||||
new Object[] { STRING_LLONG, 8 },
|
||||
new Object[] { STRING_U1, 1 }, new Object[] { STRING_U2, 2 },
|
||||
new Object[] { STRING_M12, 2 }, new Object[] { STRING_M11, 2 },
|
||||
new Object[] { STRING_UDUPLICATE, 10 },
|
||||
new Object[] { STRING_SUPPLEMENTARY, 6 }, };
|
||||
}
|
||||
|
||||
@Test(dataProvider = "provider")
|
||||
public void testLength(String str, int expected) {
|
||||
map.get(str).forEach(
|
||||
(source, data) -> {
|
||||
assertEquals(data.length(), expected, String.format(
|
||||
"testing String(%s).length(), source : %s, ",
|
||||
escapeNonASCIIs(data), source));
|
||||
});
|
||||
}
|
||||
}
|
106
jdk/test/java/lang/String/CompactString/Numbers.java
Normal file
106
jdk/test/java/lang/String/CompactString/Numbers.java
Normal file
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8077559
|
||||
* @summary Tests Compact String. This one is testing
|
||||
* Integer/Long's methods related to String.
|
||||
* @run testng/othervm -XX:+CompactStrings Numbers
|
||||
* @run testng/othervm -XX:-CompactStrings Numbers
|
||||
*/
|
||||
|
||||
public class Numbers {
|
||||
|
||||
/*
|
||||
* Data provider for testIntegerLong
|
||||
*
|
||||
* @return input parameter for testIntegerLong
|
||||
*/
|
||||
@DataProvider
|
||||
public Object[][] numbers() {
|
||||
return new Object[][] {
|
||||
{ Integer.toBinaryString(Integer.MAX_VALUE),
|
||||
"1111111111111111111111111111111" },
|
||||
{ Integer.toBinaryString(Integer.MIN_VALUE),
|
||||
"10000000000000000000000000000000" },
|
||||
{ Integer.toBinaryString(7), "111" },
|
||||
{ Integer.toBinaryString(0), "0" },
|
||||
{ Integer.toOctalString(Integer.MAX_VALUE), "17777777777" },
|
||||
{ Integer.toOctalString(Integer.MIN_VALUE), "20000000000" },
|
||||
{ Integer.toOctalString(9), "11" },
|
||||
{ Integer.toOctalString(0), "0" },
|
||||
{ Integer.toHexString(Integer.MAX_VALUE), "7fffffff" },
|
||||
{ Integer.toHexString(Integer.MIN_VALUE), "80000000" },
|
||||
{ Integer.toHexString(17), "11" },
|
||||
{ Integer.toHexString(0), "0" },
|
||||
{ Integer.toString(Integer.MAX_VALUE, 2),
|
||||
"1111111111111111111111111111111" },
|
||||
{ Integer.toString(Integer.MIN_VALUE, 2),
|
||||
"-10000000000000000000000000000000" },
|
||||
{ Integer.toString(7, 2), "111" },
|
||||
{ Integer.toString(0, 2), "0" },
|
||||
{ Integer.toString(Integer.MAX_VALUE, 8), "17777777777" },
|
||||
{ Integer.toString(Integer.MIN_VALUE, 8), "-20000000000" },
|
||||
{ Integer.toString(9, 8), "11" },
|
||||
{ Integer.toString(Integer.MAX_VALUE, 16), "7fffffff" },
|
||||
{ Integer.toString(Integer.MIN_VALUE, 16), "-80000000" },
|
||||
{ Integer.toString(17, 16), "11" },
|
||||
{ Long.toBinaryString(Long.MAX_VALUE),
|
||||
"111111111111111111111111111111111111111111111111111111111111111" },
|
||||
{ Long.toBinaryString(Long.MIN_VALUE),
|
||||
"1000000000000000000000000000000000000000000000000000000000000000" },
|
||||
{ Long.toOctalString(Long.MAX_VALUE), "777777777777777777777" },
|
||||
{ Long.toOctalString(Long.MIN_VALUE), "1000000000000000000000" },
|
||||
{ Long.toHexString(Long.MAX_VALUE), "7fffffffffffffff" },
|
||||
{ Long.toHexString(Long.MIN_VALUE), "8000000000000000" },
|
||||
{ Long.toString(Long.MAX_VALUE, 2),
|
||||
"111111111111111111111111111111111111111111111111111111111111111" },
|
||||
{ Long.toString(Long.MIN_VALUE, 2),
|
||||
"-1000000000000000000000000000000000000000000000000000000000000000" },
|
||||
{ Long.toString(Long.MAX_VALUE, 8), "777777777777777777777" },
|
||||
{ Long.toString(Long.MIN_VALUE, 8), "-1000000000000000000000" },
|
||||
{ Long.toString(Long.MAX_VALUE, 16), "7fffffffffffffff" },
|
||||
{ Long.toString(Long.MIN_VALUE, 16), "-8000000000000000" } };
|
||||
}
|
||||
|
||||
/*
|
||||
* test Integer/Long's methods related to String.
|
||||
*
|
||||
* @param res
|
||||
* real result
|
||||
* @param expected
|
||||
* expected result
|
||||
*/
|
||||
@Test(dataProvider = "numbers")
|
||||
public void testIntegerLong(String res, String expected) {
|
||||
assertEquals(res, expected);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8077559
|
||||
* @summary Tests Compact String. This one is for String.offsetByCodePoints.
|
||||
* @run testng/othervm -XX:+CompactStrings OffsetByCodePoints
|
||||
* @run testng/othervm -XX:-CompactStrings OffsetByCodePoints
|
||||
*/
|
||||
|
||||
public class OffsetByCodePoints extends CompactString {
|
||||
|
||||
@DataProvider
|
||||
public Object[][] provider() {
|
||||
return new Object[][] {
|
||||
|
||||
new Object[] { STRING_SUPPLEMENTARY, 0, 1, 2 },
|
||||
new Object[] { STRING_SUPPLEMENTARY, 0, 3, 5 },
|
||||
new Object[] { STRING_SUPPLEMENTARY, 1, 1, 2 },
|
||||
new Object[] { STRING_SUPPLEMENTARY, 1, 3, 5 },
|
||||
new Object[] { STRING_SUPPLEMENTARY, 2, 1, 4 },
|
||||
new Object[] { STRING_SUPPLEMENTARY, 2, 2, 5 },
|
||||
new Object[] { STRING_SUPPLEMENTARY, 2, 3, 6 },
|
||||
new Object[] { STRING_SUPPLEMENTARY, 3, 1, 4 },
|
||||
new Object[] { STRING_SUPPLEMENTARY, 3, 2, 5 },
|
||||
new Object[] { STRING_SUPPLEMENTARY, 3, 3, 6 }, };
|
||||
}
|
||||
|
||||
@Test(dataProvider = "provider")
|
||||
public void testOffsetByCodePoints(String str, int index,
|
||||
int codePointOffset, int expected) {
|
||||
map.get(str)
|
||||
.forEach(
|
||||
(source, data) -> {
|
||||
assertEquals(
|
||||
data.offsetByCodePoints(index,
|
||||
codePointOffset),
|
||||
expected,
|
||||
String.format(
|
||||
"testing String(%s).offsetByCodePoints(%d, %d), source : %s, ",
|
||||
escapeNonASCIIs(data), index,
|
||||
codePointOffset, source));
|
||||
});
|
||||
}
|
||||
}
|
105
jdk/test/java/lang/String/CompactString/RegionMatches.java
Normal file
105
jdk/test/java/lang/String/CompactString/RegionMatches.java
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8077559
|
||||
* @summary Tests Compact String. This one is for String.regionMatches.
|
||||
* @run testng/othervm -XX:+CompactStrings RegionMatches
|
||||
* @run testng/othervm -XX:-CompactStrings RegionMatches
|
||||
*/
|
||||
|
||||
public class RegionMatches extends CompactString {
|
||||
|
||||
@DataProvider
|
||||
public Object[][] provider() {
|
||||
return new Object[][] {
|
||||
|
||||
new Object[] { STRING_EMPTY, true, 0, "", 0, 0, true },
|
||||
new Object[] { STRING_EMPTY, true, 0, "", 0, 1, false },
|
||||
new Object[] { STRING_EMPTY, true, 0, "A", 0, 0, true },
|
||||
new Object[] { STRING_EMPTY, true, 0, "", 0, 0, true },
|
||||
new Object[] { STRING_EMPTY, true, 0, "", 0, 1, false },
|
||||
new Object[] { STRING_L1, false, 0, "a", 0, 1, false },
|
||||
new Object[] { STRING_L1, false, 0, "BA", 1, 1, true },
|
||||
new Object[] { STRING_L1, false, 0, "Ba", 1, 1, false },
|
||||
new Object[] { STRING_L1, true, 0, "a", 0, 1, true },
|
||||
new Object[] { STRING_L1, true, 0, "BA", 1, 1, true },
|
||||
new Object[] { STRING_L1, true, 0, "Ba", 1, 1, true },
|
||||
new Object[] { STRING_L2, true, 1, "b", 0, 1, true },
|
||||
new Object[] { STRING_L2, true, 1, "B", 0, 1, true },
|
||||
new Object[] { STRING_L2, true, 0, "xaBc", 1, 2, true },
|
||||
new Object[] { STRING_L2, false, 0, "AB", 0, 2, true },
|
||||
new Object[] { STRING_L2, false, 0, "Ab", 0, 2, false },
|
||||
new Object[] { STRING_L2, false, 1, "BAB", 2, 1, true },
|
||||
new Object[] { STRING_LLONG, true, 1, "bCdEF", 0, 5, true },
|
||||
new Object[] { STRING_LLONG, false, 2, "CDEFG", 0, 5, true },
|
||||
new Object[] { STRING_LLONG, true, 2, "CDEFg", 0, 5, true },
|
||||
new Object[] { STRING_U1, true, 0, "\uFF41", 0, 1, true },
|
||||
new Object[] { STRING_U1, false, 0, "\uFF41", 0, 1, false },
|
||||
new Object[] { STRING_MDUPLICATE1, true, 0, "\uFF41a\uFF41", 0,
|
||||
3, true },
|
||||
new Object[] { STRING_MDUPLICATE1, false, 0, "\uFF21a\uFF21",
|
||||
0, 3, false },
|
||||
new Object[] { STRING_SUPPLEMENTARY, true, 1, "\uDC00\uD801",
|
||||
0, 2, true },
|
||||
new Object[] { STRING_SUPPLEMENTARY, true, 4, "\uFF21", 0, 1,
|
||||
true },
|
||||
new Object[] { STRING_SUPPLEMENTARY, true, 5, "A", 0, 1, true },
|
||||
new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, false, 0,
|
||||
"\uD801\uDC28\uD801\uDC29", 0, 4, true },
|
||||
new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, true, 1,
|
||||
"\uDC28\uD801", 0, 2, true },
|
||||
new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, true, 1,
|
||||
"\uDC00\uD801", 0, 2, false },
|
||||
new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, true, 4,
|
||||
"\uFF21", 0, 1, true },
|
||||
new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, false, 4,
|
||||
"\uFF21", 0, 1, false },
|
||||
new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, false, 4,
|
||||
"\uFF41", 0, 1, true }, };
|
||||
}
|
||||
|
||||
@Test(dataProvider = "provider")
|
||||
public void testRegionMatches(String str, boolean ignoreCase, int toffset,
|
||||
String other, int ooffset, int len, boolean expected) {
|
||||
map.get(str)
|
||||
.forEach(
|
||||
(source, data) -> {
|
||||
assertEquals(
|
||||
data.regionMatches(ignoreCase, toffset,
|
||||
other, ooffset, len),
|
||||
expected,
|
||||
String.format(
|
||||
"testing String(%s).regionMatches(%b, %d, %s, %d, %d), source : %s, ",
|
||||
escapeNonASCIIs(data), ignoreCase,
|
||||
toffset, escapeNonASCIIs(other),
|
||||
ooffset, len, source));
|
||||
});
|
||||
}
|
||||
}
|
117
jdk/test/java/lang/String/CompactString/Replace.java
Normal file
117
jdk/test/java/lang/String/CompactString/Replace.java
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8077559
|
||||
* @summary Tests Compact String. This one is for String.replace.
|
||||
* @run testng/othervm -XX:+CompactStrings Replace
|
||||
* @run testng/othervm -XX:-CompactStrings Replace
|
||||
*/
|
||||
|
||||
public class Replace extends CompactString {
|
||||
|
||||
@DataProvider
|
||||
public Object[][] provider() {
|
||||
return new Object[][] {
|
||||
|
||||
new Object[] { STRING_L1, 'A', 'B', "B" },
|
||||
new Object[] { STRING_L1, 'A', 'A', "A" },
|
||||
new Object[] { STRING_L1, 'A', '\uFF21', "\uFF21" },
|
||||
new Object[] { STRING_L2, 'A', 'B', "BB" },
|
||||
new Object[] { STRING_L2, 'B', 'A', "AA" },
|
||||
new Object[] { STRING_L2, 'C', 'A', "AB" },
|
||||
new Object[] { STRING_L2, 'B', '\uFF21', "A\uFF21" },
|
||||
new Object[] { STRING_U1, '\uFF21', 'A', "A" },
|
||||
new Object[] { STRING_U1, '\uFF22', 'A', "\uFF21" },
|
||||
new Object[] { STRING_U2, '\uFF22', 'A', "\uFF21A" },
|
||||
new Object[] { STRING_M12, 'A', '\uFF21', "\uFF21\uFF21" },
|
||||
new Object[] { STRING_M11, '\uFF21', 'A', "AA" },
|
||||
new Object[] { STRING_UDUPLICATE, '\uFF21', 'A',
|
||||
"A\uFF22A\uFF22A\uFF22A\uFF22A\uFF22" },
|
||||
new Object[] { STRING_MDUPLICATE1, '\uFF21', 'A', "AAAAAAAAAA" },
|
||||
new Object[] { STRING_MDUPLICATE1, 'A', '\uFF21',
|
||||
"\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21" }, };
|
||||
}
|
||||
|
||||
@Test(dataProvider = "provider")
|
||||
public void testReplace(String str, char oldChar, char newChar,
|
||||
String expected) {
|
||||
map.get(str)
|
||||
.forEach(
|
||||
(source, data) -> {
|
||||
assertEquals(
|
||||
data.replace(oldChar, newChar),
|
||||
expected,
|
||||
String.format(
|
||||
"testing String(%s).replace(%s, %s), source : %s, ",
|
||||
escapeNonASCIIs(data),
|
||||
escapeNonASCII(oldChar),
|
||||
escapeNonASCII(newChar), source));
|
||||
});
|
||||
}
|
||||
|
||||
@DataProvider
|
||||
public Object[][] provider2() {
|
||||
return new Object[][] {
|
||||
|
||||
new Object[] { STRING_EMPTY, "", "ABC", "ABC" },
|
||||
new Object[] { STRING_EMPTY, "", "", "" },
|
||||
new Object[] { STRING_L1, "A", "B", "B" },
|
||||
new Object[] { STRING_L1, "A", "A", "A" },
|
||||
new Object[] { STRING_L2, "B", "\uFF21", "A\uFF21" },
|
||||
new Object[] { STRING_LLONG, "BCD", "\uFF21", "A\uFF21EFGH" },
|
||||
new Object[] { STRING_U1, "\uFF21", "A", "A" },
|
||||
new Object[] { STRING_U1, "\uFF21", "A\uFF21", "A\uFF21" },
|
||||
new Object[] { STRING_U2, "\uFF21", "A", "A\uFF22" },
|
||||
new Object[] { STRING_U2, "\uFF22", "A", "\uFF21A" },
|
||||
new Object[] { STRING_UDUPLICATE, "\uFF21\uFF22", "AB",
|
||||
"ABABABABAB" },
|
||||
new Object[] { STRING_MDUPLICATE1, "\uFF21", "A", "AAAAAAAAAA" },
|
||||
new Object[] { STRING_MDUPLICATE1, "A", "\uFF21",
|
||||
"\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21" }, };
|
||||
}
|
||||
|
||||
@Test(dataProvider = "provider2")
|
||||
public void testReplace(String str, CharSequence target,
|
||||
CharSequence replacement, String expected) {
|
||||
map.get(str)
|
||||
.forEach(
|
||||
(source, data) -> {
|
||||
assertEquals(
|
||||
data.replace(target, replacement),
|
||||
expected,
|
||||
String.format(
|
||||
"testing String(%s).replace(%s, %s), source : %s, ",
|
||||
escapeNonASCIIs(data),
|
||||
escapeNonASCIIs(target.toString()),
|
||||
escapeNonASCIIs(replacement
|
||||
.toString()), source));
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static jdk.testlibrary.SerializationUtils.*;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8077559
|
||||
* @library /lib/testlibrary
|
||||
* @build jdk.testlibrary.SerializationUtils
|
||||
* @summary Tests Compact String. This one is testing String serialization
|
||||
* among -XX:+CompactStrings/-XX:-CompactStrings/LegacyString
|
||||
* @run testng/othervm -XX:+CompactStrings SerializationTest
|
||||
* @run testng/othervm -XX:-CompactStrings SerializationTest
|
||||
*/
|
||||
|
||||
public class SerializationTest {
|
||||
@DataProvider
|
||||
public Object[][] provider() {
|
||||
return new Object[][] {
|
||||
// every byte array is serialized from corresponding String object
|
||||
// by previous JDK(build 1.8.0_45-b14).
|
||||
new Object[] { "", new byte[] { -84, -19, 0, 5, 116, 0, 0 } },
|
||||
new Object[] { "A", new byte[] { -84, -19, 0, 5, 116, 0, 1, 65 } },
|
||||
new Object[] { "AB", new byte[] { -84, -19, 0, 5, 116, 0, 2, 65, 66 } },
|
||||
new Object[] { "abcdefghijk",
|
||||
new byte[] {-84, -19, 0, 5, 116, 0, 11, 97, 98, 99, 100, 101,
|
||||
102, 103, 104, 105, 106, 107 } },
|
||||
new Object[] { "\uff21", new byte[] { -84, -19, 0, 5, 116, 0, 3, -17, -68, -95 } },
|
||||
new Object[] { "\uff21\uff22", new byte[] { -84, -19, 0, 5, 116, 0, 6, -17, -68,
|
||||
-95, -17, -68, -94 } },
|
||||
new Object[] { "\uff21A\uff21A\uff21A\uff21A\uff21A",
|
||||
new byte[] { -84, -19, 0, 5, 116, 0, 20, -17, -68, -95, 65, -17, -68,
|
||||
-95, 65, -17, -68, -95, 65, -17, -68, -95, 65, -17, -68, -95, 65 } },
|
||||
new Object[] { "A\uff21B\uff22C\uff23D\uff24E\uff25F\uff26G\uff27H\uff28",
|
||||
new byte[] { -84, -19, 0, 5, 116, 0, 32, 65, -17, -68, -95, 66, -17, -68,
|
||||
-94, 67, -17, -68, -93, 68, -17, -68, -92, 69, -17, -68, -91, 70, -17,
|
||||
-68, -90, 71, -17, -68, -89, 72, -17, -68, -88 } },
|
||||
new Object[] { "\uff21A\uff22B\uff23C\uff24D\uff25E\uff26F\uff27G\uff28H",
|
||||
new byte[] { -84, -19, 0, 5, 116, 0, 32, -17, -68, -95, 65, -17, -68,
|
||||
-94, 66, -17, -68, -93, 67, -17, -68, -92, 68, -17, -68, -91, 69, -17,
|
||||
-68, -90, 70, -17, -68, -89, 71, -17, -68, -88, 72 } },
|
||||
new Object[] { "\ud801\udc00\ud801\udc01\uff21A",
|
||||
new byte[] { -84, -19, 0, 5, 116, 0, 16, -19, -96, -127, -19, -80, -128,
|
||||
-19, -96, -127, -19, -80, -127, -17, -68, -95, 65 } },
|
||||
new Object[] { "\uff21\uff22\uff21\uff22\uff21\uff22\uff21\uff22\uff21\uff22",
|
||||
new byte[] { -84, -19, 0, 5, 116, 0, 30, -17, -68, -95, -17, -68, -94, -17,
|
||||
-68, -95, -17, -68, -94, -17, -68, -95, -17, -68, -94, -17, -68, -95, -17,
|
||||
-68, -94, -17, -68, -95, -17, -68, -94 } } };
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify serialization works between Compact String/Legacy String
|
||||
*/
|
||||
@Test(dataProvider = "provider")
|
||||
public void test(String strContent, byte[] baInJDK8) throws Exception {
|
||||
// Serialize a String object into byte array.
|
||||
byte[] ba = serialize(strContent);
|
||||
assertEquals(ba, baInJDK8);
|
||||
// Deserialize a String object from byte array which is generated by previous JDK(build 1.8.0_45-b14).
|
||||
Object obj = deserialize(ba);
|
||||
assertEquals(obj.getClass(), String.class);
|
||||
assertEquals((String)obj, strContent);
|
||||
}
|
||||
}
|
181
jdk/test/java/lang/String/CompactString/Split.java
Normal file
181
jdk/test/java/lang/String/CompactString/Split.java
Normal file
@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8077559
|
||||
* @summary Tests Compact String. This one is for String.split.
|
||||
* @run testng/othervm -XX:+CompactStrings Split
|
||||
* @run testng/othervm -XX:-CompactStrings Split
|
||||
*/
|
||||
|
||||
public class Split extends CompactString {
|
||||
|
||||
@DataProvider
|
||||
public Object[][] provider() {
|
||||
return new Object[][] {
|
||||
new Object[] { STRING_L1, "", 0, new String[] { "A" } },
|
||||
new Object[] { STRING_L1, "", 1, new String[] { "A" } },
|
||||
new Object[] { STRING_L1, "", 2, new String[] { "A", "" } },
|
||||
new Object[] { STRING_L1, "A", 0, new String[] {} },
|
||||
new Object[] { STRING_L2, "A", 0, new String[] { "", "B" } },
|
||||
new Object[] { STRING_L2, "B", 0, new String[] { "A" } },
|
||||
new Object[] { STRING_LLONG, "D", 0,
|
||||
new String[] { "ABC", "EFGH" } },
|
||||
new Object[] { STRING_LLONG, "[D]", 0,
|
||||
new String[] { "ABC", "EFGH" } },
|
||||
new Object[] { STRING_LLONG, "CD", 0,
|
||||
new String[] { "AB", "EFGH" } },
|
||||
new Object[] { STRING_LLONG, "DC", 0,
|
||||
new String[] { "ABCDEFGH" } },
|
||||
new Object[] { STRING_LLONG, "[CF]", 0,
|
||||
new String[] { "AB", "DE", "GH" } },
|
||||
new Object[] { STRING_LLONG, "[CF]", 1,
|
||||
new String[] { "ABCDEFGH" } },
|
||||
new Object[] { STRING_LLONG, "[CF]", 2,
|
||||
new String[] { "AB", "DEFGH" } },
|
||||
new Object[] { STRING_LLONG, "[FC]", 0,
|
||||
new String[] { "AB", "DE", "GH" } },
|
||||
new Object[] { STRING_LLONG, "[FC]", 1,
|
||||
new String[] { "ABCDEFGH" } },
|
||||
new Object[] { STRING_LLONG, "[FC]", 2,
|
||||
new String[] { "AB", "DEFGH" } },
|
||||
new Object[] { STRING_U1, "", 0, new String[] { "\uFF21" } },
|
||||
new Object[] { STRING_U1, "", 1, new String[] { "\uFF21" } },
|
||||
new Object[] { STRING_U1, "", 2, new String[] { "\uFF21", "" } },
|
||||
new Object[] { STRING_U1, "\uFF21", 0, new String[] {} },
|
||||
new Object[] { STRING_M12, "\uFF21", 0,
|
||||
new String[] { "", "A" } },
|
||||
new Object[] { STRING_M12, "A", 0, new String[] { "\uFF21" } },
|
||||
new Object[] {
|
||||
STRING_UDUPLICATE,
|
||||
"\uFF21",
|
||||
0,
|
||||
new String[] { "", "\uFF22", "\uFF22", "\uFF22",
|
||||
"\uFF22", "\uFF22" } },
|
||||
new Object[] {
|
||||
STRING_UDUPLICATE,
|
||||
"\uFF21",
|
||||
2,
|
||||
new String[] { "",
|
||||
"\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22" } },
|
||||
new Object[] {
|
||||
STRING_UDUPLICATE,
|
||||
"\uFF21",
|
||||
4,
|
||||
new String[] { "", "\uFF22", "\uFF22",
|
||||
"\uFF22\uFF21\uFF22\uFF21\uFF22" } },
|
||||
new Object[] {
|
||||
STRING_UDUPLICATE,
|
||||
"\uFF22",
|
||||
0,
|
||||
new String[] { "\uFF21", "\uFF21", "\uFF21", "\uFF21",
|
||||
"\uFF21" } },
|
||||
new Object[] {
|
||||
STRING_UDUPLICATE,
|
||||
"\uFF22",
|
||||
3,
|
||||
new String[] { "\uFF21", "\uFF21",
|
||||
"\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22" } },
|
||||
|
||||
new Object[] { STRING_MDUPLICATE1, "\uFF21", 0,
|
||||
new String[] { "", "A", "A", "A", "A", "A" } },
|
||||
new Object[] { STRING_MDUPLICATE1, "\uFF21", 3,
|
||||
new String[] { "", "A", "A\uFF21A\uFF21A\uFF21A" } },
|
||||
new Object[] {
|
||||
STRING_MDUPLICATE1,
|
||||
"A",
|
||||
0,
|
||||
new String[] { "\uFF21", "\uFF21", "\uFF21", "\uFF21",
|
||||
"\uFF21" } },
|
||||
new Object[] {
|
||||
STRING_MDUPLICATE1,
|
||||
"A",
|
||||
4,
|
||||
new String[] { "\uFF21", "\uFF21", "\uFF21",
|
||||
"\uFF21A\uFF21A" } },
|
||||
new Object[] { STRING_SUPPLEMENTARY, "\uD801\uDC01", 0,
|
||||
new String[] { "\uD801\uDC00", "\uFF21A" } },
|
||||
new Object[] { STRING_SUPPLEMENTARY, "\uDC01", 0,
|
||||
new String[] { "\uD801\uDC00\uD801\uDC01\uFF21A" } },
|
||||
new Object[] { STRING_SUPPLEMENTARY, "\uD801\uDC01", 0,
|
||||
new String[] { "\uD801\uDC00", "\uFF21A" } },
|
||||
new Object[] { STRING_SUPPLEMENTARY, "[\uD801\uDC01\uFF21]", 0,
|
||||
new String[] { "\uD801\uDC00", "", "A" } },
|
||||
new Object[] { STRING_SUPPLEMENTARY, "[\uD801\uDC01\uFF21]", 1,
|
||||
new String[] { "\uD801\uDC00\uD801\uDC01\uFF21A" } },
|
||||
new Object[] { STRING_SUPPLEMENTARY, "[\uD801\uDC01\uFF21]", 2,
|
||||
new String[] { "\uD801\uDC00", "\uFF21A" } },
|
||||
new Object[] { STRING_SUPPLEMENTARY, "[\uFF21\uD801\uDC01]", 0,
|
||||
new String[] { "\uD801\uDC00", "", "A" } },
|
||||
new Object[] { STRING_SUPPLEMENTARY, "[\uFF21\uD801\uDC01]", 1,
|
||||
new String[] { "\uD801\uDC00\uD801\uDC01\uFF21A" } },
|
||||
new Object[] { STRING_SUPPLEMENTARY, "[\uFF21\uD801\uDC01]", 2,
|
||||
new String[] { "\uD801\uDC00", "\uFF21A" } },
|
||||
new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, "\uDC01", 0,
|
||||
new String[] { "\uD801\uDC28\uD801\uDC29\uFF41a" } },
|
||||
new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, "\uD801\uDC29",
|
||||
0, new String[] { "\uD801\uDC28", "\uFF41a" } },
|
||||
new Object[] { STRING_SUPPLEMENTARY_LOWERCASE,
|
||||
"[\uD801\uDC29\uFF41]", 0,
|
||||
new String[] { "\uD801\uDC28", "", "a" } },
|
||||
new Object[] { STRING_SUPPLEMENTARY_LOWERCASE,
|
||||
"[\uD801\uDC29\uFF41]", 1,
|
||||
new String[] { "\uD801\uDC28\uD801\uDC29\uFF41a" } },
|
||||
new Object[] { STRING_SUPPLEMENTARY_LOWERCASE,
|
||||
"[\uD801\uDC29\uFF41]", 2,
|
||||
new String[] { "\uD801\uDC28", "\uFF41a" } },
|
||||
new Object[] { STRING_SUPPLEMENTARY_LOWERCASE,
|
||||
"[\uFF41\uD801\uDC29]", 0,
|
||||
new String[] { "\uD801\uDC28", "", "a" } },
|
||||
new Object[] { STRING_SUPPLEMENTARY_LOWERCASE,
|
||||
"[\uFF41\uD801\uDC29]", 1,
|
||||
new String[] { "\uD801\uDC28\uD801\uDC29\uFF41a" } },
|
||||
new Object[] { STRING_SUPPLEMENTARY_LOWERCASE,
|
||||
"[\uFF41\uD801\uDC29]", 2,
|
||||
new String[] { "\uD801\uDC28", "\uFF41a" } }, };
|
||||
}
|
||||
|
||||
@Test(dataProvider = "provider")
|
||||
public void testSplit(String str, String regex, int limit, String[] expected) {
|
||||
map.get(str)
|
||||
.forEach(
|
||||
(source, data) -> {
|
||||
assertTrue(
|
||||
Arrays.equals(data.split(regex, limit),
|
||||
expected),
|
||||
String.format(
|
||||
"testing String(%s).split(%s, %d), source : %s, ",
|
||||
escapeNonASCIIs(data),
|
||||
escapeNonASCIIs(regex), limit,
|
||||
source));
|
||||
});
|
||||
}
|
||||
}
|
109
jdk/test/java/lang/String/CompactString/StartsWith.java
Normal file
109
jdk/test/java/lang/String/CompactString/StartsWith.java
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8077559
|
||||
* @summary Tests Compact String. This one is for String.startsWith.
|
||||
* @run testng/othervm -XX:+CompactStrings StartsWith
|
||||
* @run testng/othervm -XX:-CompactStrings StartsWith
|
||||
*/
|
||||
|
||||
public class StartsWith extends CompactString {
|
||||
|
||||
@DataProvider
|
||||
public Object[][] provider() {
|
||||
return new Object[][] {
|
||||
new Object[] {STRING_EMPTY, "", 0, true},
|
||||
new Object[] {STRING_EMPTY, "A", 0, false},
|
||||
new Object[] {STRING_EMPTY, "", 0, true},
|
||||
new Object[] {STRING_EMPTY, "", -1, false},
|
||||
new Object[] {STRING_L1, "A", 0, true},
|
||||
new Object[] {STRING_L1, "A", -1, false},
|
||||
new Object[] {STRING_L1, "A", 1, false},
|
||||
new Object[] {STRING_L2, "B", 1, true},
|
||||
new Object[] {STRING_L2, "B", 0, false},
|
||||
new Object[] {STRING_L2, "A", 0, true},
|
||||
new Object[] {STRING_L2, "AB", 1, false},
|
||||
new Object[] {STRING_L4, "ABC", 0, true},
|
||||
new Object[] {STRING_LLONG, "ABCDEFGH", 0, true},
|
||||
new Object[] {STRING_LLONG, "ABCDE", 0, true},
|
||||
new Object[] {STRING_LLONG, "CDE", 0, false},
|
||||
new Object[] {STRING_LLONG, "FG", 5, true},
|
||||
new Object[] {STRING_U1, "\uFF21", 0, true},
|
||||
new Object[] {STRING_U1, "", 1, true},
|
||||
new Object[] {STRING_U1, "\uFF21", 0, true},
|
||||
new Object[] {STRING_U1, "A", 0, false},
|
||||
new Object[] {STRING_U2, "\uFF21\uFF22", 0, true},
|
||||
new Object[] {STRING_U2, "\uFF21", 0, true},
|
||||
new Object[] {STRING_U2, "\uFF22", 0, false},
|
||||
new Object[] {STRING_U2, "", 0, true},
|
||||
new Object[] {STRING_M12, "\uFF21", 0, true},
|
||||
new Object[] {STRING_M12, "\uFF21A", 0, true},
|
||||
new Object[] {STRING_M12, "A", 0, false},
|
||||
new Object[] {STRING_M12, "\uFF21A", 0, true},
|
||||
new Object[] {STRING_M12, "A", 1, true},
|
||||
new Object[] {STRING_M11, "A", 0, true},
|
||||
new Object[] {STRING_M11, "A\uFF21", 0, true},
|
||||
new Object[] {STRING_M11, "A\uFF21", 0, true},
|
||||
new Object[] {STRING_M11, "\uFF21", 1, true},
|
||||
new Object[] {STRING_UDUPLICATE,
|
||||
"\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22",
|
||||
0, true},
|
||||
new Object[] {STRING_UDUPLICATE,
|
||||
"\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22", 0, true},
|
||||
new Object[] {STRING_UDUPLICATE,
|
||||
"\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22", 2, true},
|
||||
new Object[] {STRING_UDUPLICATE,
|
||||
"\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22", 5, false},
|
||||
new Object[] {STRING_MDUPLICATE1,
|
||||
"\uFF21A\uFF21A\uFF21A\uFF21A\uFF21A", 0, true},
|
||||
new Object[] {STRING_MDUPLICATE1,
|
||||
"\uFF21A\uFF21A\uFF21A\uFF21A\uFF21", 0, true},
|
||||
new Object[] {STRING_MDUPLICATE1, "A\uFF21A\uFF21A\uFF21A", 1, true},
|
||||
new Object[] {STRING_SUPPLEMENTARY, "\uDC01\uFF21", 3, true},
|
||||
};
|
||||
}
|
||||
|
||||
@Test(dataProvider = "provider")
|
||||
public void testStartsWith(String str, String prefix, int toffset,
|
||||
boolean expected) {
|
||||
map.get(str)
|
||||
.forEach(
|
||||
(source, data) -> {
|
||||
assertEquals(
|
||||
data.startsWith(prefix, toffset),
|
||||
expected,
|
||||
String.format(
|
||||
"testing String(%s).startsWith(%s, %d), source : %s, ",
|
||||
escapeNonASCIIs(data),
|
||||
escapeNonASCIIs(prefix), toffset,
|
||||
source));
|
||||
});
|
||||
}
|
||||
}
|
84
jdk/test/java/lang/String/CompactString/SubString.java
Normal file
84
jdk/test/java/lang/String/CompactString/SubString.java
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8077559
|
||||
* @summary Tests Compact String. This one is for String.subString.
|
||||
* @run testng/othervm -XX:+CompactStrings SubString
|
||||
* @run testng/othervm -XX:-CompactStrings SubString
|
||||
*/
|
||||
|
||||
public class SubString extends CompactString {
|
||||
|
||||
@DataProvider
|
||||
public Object[][] provider() {
|
||||
return new Object[][] {
|
||||
|
||||
new Object[] { STRING_EMPTY, 0, 0, "" },
|
||||
new Object[] { STRING_L1, 0, 1, "A" },
|
||||
new Object[] { STRING_L1, 1, 1, "" },
|
||||
new Object[] { STRING_L2, 0, 2, "AB" },
|
||||
new Object[] { STRING_L2, 1, 2, "B" },
|
||||
new Object[] { STRING_LLONG, 0, 8, "ABCDEFGH" },
|
||||
new Object[] { STRING_LLONG, 7, 8, "H" },
|
||||
new Object[] { STRING_LLONG, 8, 8, "" },
|
||||
new Object[] { STRING_LLONG, 3, 7, "DEFG" },
|
||||
new Object[] { STRING_U1, 0, 1, "\uFF21" },
|
||||
new Object[] { STRING_U1, 1, 1, "" },
|
||||
new Object[] { STRING_U1, 0, 0, "" },
|
||||
new Object[] { STRING_U2, 0, 2, "\uFF21\uFF22" },
|
||||
new Object[] { STRING_U2, 1, 2, "\uFF22" },
|
||||
new Object[] { STRING_U2, 2, 2, "" },
|
||||
new Object[] { STRING_U2, 0, 2, "\uFF21\uFF22" },
|
||||
new Object[] { STRING_U2, 1, 2, "\uFF22" },
|
||||
new Object[] { STRING_M12, 1, 2, "A" },
|
||||
new Object[] { STRING_M11, 0, 1, "A" },
|
||||
new Object[] { STRING_M11, 1, 2, "\uFF21" },
|
||||
new Object[] { STRING_UDUPLICATE, 1, 5,
|
||||
"\uFF22\uFF21\uFF22\uFF21" },
|
||||
new Object[] { STRING_MDUPLICATE1, 9, 10, "A" },
|
||||
new Object[] { STRING_MDUPLICATE1, 7, 8, "A" }, };
|
||||
}
|
||||
|
||||
@Test(dataProvider = "provider")
|
||||
public void testSubstring(String str, int beginIndex, int endIndex,
|
||||
String expected) {
|
||||
map.get(str)
|
||||
.forEach(
|
||||
(source, data) -> {
|
||||
assertEquals(
|
||||
data.substring(beginIndex, endIndex),
|
||||
expected,
|
||||
String.format(
|
||||
"testing String(%s).substring(%d, %d), source : %s, ",
|
||||
escapeNonASCIIs(data), beginIndex,
|
||||
endIndex, source));
|
||||
});
|
||||
}
|
||||
}
|
67
jdk/test/java/lang/String/CompactString/ToCharArray.java
Normal file
67
jdk/test/java/lang/String/CompactString/ToCharArray.java
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8077559
|
||||
* @summary Tests Compact String. This one is for String.toCharArray.
|
||||
* @run testng/othervm -XX:+CompactStrings ToCharArray
|
||||
* @run testng/othervm -XX:-CompactStrings ToCharArray
|
||||
*/
|
||||
|
||||
public class ToCharArray extends CompactString {
|
||||
|
||||
@DataProvider
|
||||
public Object[][] provider() {
|
||||
return new Object[][] {
|
||||
new Object[] { STRING_EMPTY, new char[] {} },
|
||||
new Object[] { STRING_L1, new char[] { 'A' } },
|
||||
new Object[] { STRING_L2, new char[] { 'A', 'B' } },
|
||||
new Object[] { STRING_LLONG,
|
||||
new char[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' } },
|
||||
new Object[] { STRING_U1, new char[] { '\uFF21' } },
|
||||
new Object[] { STRING_U2, new char[] { '\uFF21', '\uFF22' } },
|
||||
new Object[] { STRING_M12, new char[] { '\uFF21', 'A' } },
|
||||
new Object[] { STRING_M11, new char[] { 'A', '\uFF21' } }, };
|
||||
}
|
||||
|
||||
@Test(dataProvider = "provider")
|
||||
public void testToCharArray(String str, char[] expected) {
|
||||
map.get(str)
|
||||
.forEach(
|
||||
(source, data) -> {
|
||||
assertTrue(
|
||||
Arrays.equals(data.toCharArray(), expected),
|
||||
String.format(
|
||||
"testing String(%s).toCharArray(), source : %s, ",
|
||||
escapeNonASCIIs(data), source));
|
||||
});
|
||||
}
|
||||
}
|
66
jdk/test/java/lang/String/CompactString/ToLowerCase.java
Normal file
66
jdk/test/java/lang/String/CompactString/ToLowerCase.java
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8077559
|
||||
* @summary Tests Compact String. This one is for String.toLowerCase.
|
||||
* @run testng/othervm -XX:+CompactStrings ToLowerCase
|
||||
* @run testng/othervm -XX:-CompactStrings ToLowerCase
|
||||
*/
|
||||
|
||||
public class ToLowerCase extends CompactString {
|
||||
|
||||
@DataProvider
|
||||
public Object[][] provider() {
|
||||
return new Object[][] {
|
||||
new Object[] { STRING_EMPTY, "" },
|
||||
new Object[] { STRING_L1, "a" },
|
||||
new Object[] { STRING_L2, "ab" },
|
||||
new Object[] { STRING_U1, "\uFF41" },
|
||||
new Object[] { STRING_MDUPLICATE1,
|
||||
"\uFF41a\uFF41a\uFF41a\uFF41a\uFF41a" },
|
||||
new Object[] { STRING_SUPPLEMENTARY,
|
||||
"\uD801\uDC28\uD801\uDC29\uFF41a" },
|
||||
new Object[] { STRING_SUPPLEMENTARY_LOWERCASE,
|
||||
"\uD801\uDC28\uD801\uDC29\uFF41a" },
|
||||
new Object[] { STRING_SUPPLEMENTARY,
|
||||
STRING_SUPPLEMENTARY_LOWERCASE } };
|
||||
}
|
||||
|
||||
@Test(dataProvider = "provider")
|
||||
public void testToLowerCase(String str, String expected) {
|
||||
map.get(str).forEach(
|
||||
(source, data) -> {
|
||||
assertEquals(data.toLowerCase(), expected, String.format(
|
||||
"testing String(%s).toLowerCase(), source : %s, ",
|
||||
escapeNonASCIIs(data), source));
|
||||
});
|
||||
}
|
||||
}
|
67
jdk/test/java/lang/String/CompactString/ToUpperCase.java
Normal file
67
jdk/test/java/lang/String/CompactString/ToUpperCase.java
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8077559
|
||||
* @summary Tests Compact String. This one is for String.toUpperCase.
|
||||
* @run testng/othervm -XX:+CompactStrings ToUpperCase
|
||||
* @run testng/othervm -XX:-CompactStrings ToUpperCase
|
||||
*/
|
||||
|
||||
public class ToUpperCase extends CompactString {
|
||||
|
||||
@DataProvider
|
||||
public Object[][] provider() {
|
||||
return new Object[][] {
|
||||
|
||||
new Object[] { STRING_EMPTY, "" },
|
||||
new Object[] { STRING_L1, "A" },
|
||||
new Object[] { STRING_L2, "AB" },
|
||||
new Object[] { STRING_U1, "\uFF21" },
|
||||
new Object[] { STRING_MDUPLICATE1,
|
||||
"\uFF21A\uFF21A\uFF21A\uFF21A\uFF21A" },
|
||||
new Object[] { STRING_SUPPLEMENTARY,
|
||||
"\uD801\uDC00\uD801\uDC01\uFF21A" },
|
||||
|
||||
new Object[] { STRING_SUPPLEMENTARY_LOWERCASE,
|
||||
"\uD801\uDC00\uD801\uDC01\uFF21A" },
|
||||
new Object[] { STRING_SUPPLEMENTARY_LOWERCASE,
|
||||
STRING_SUPPLEMENTARY }, };
|
||||
}
|
||||
|
||||
@Test(dataProvider = "provider")
|
||||
public void testToUpperCase(String str, String expected) {
|
||||
map.get(str).forEach(
|
||||
(source, data) -> {
|
||||
assertEquals(data.toUpperCase(), expected, String.format(
|
||||
"testing String(%s).toUpperCase(), source : %s, ",
|
||||
escapeNonASCIIs(data), source));
|
||||
});
|
||||
}
|
||||
}
|
71
jdk/test/java/lang/String/CompactString/Trim.java
Normal file
71
jdk/test/java/lang/String/CompactString/Trim.java
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8077559
|
||||
* @summary Tests Compact String. This one is for String.trim.
|
||||
* @run testng/othervm -XX:+CompactStrings Trim
|
||||
* @run testng/othervm -XX:-CompactStrings Trim
|
||||
*/
|
||||
|
||||
public class Trim {
|
||||
|
||||
/*
|
||||
* Data provider for testTrim
|
||||
*
|
||||
* @return input parameter for testTrim
|
||||
*/
|
||||
@DataProvider
|
||||
public Object[][] trims() {
|
||||
return new Object[][] {
|
||||
{ " \t \t".trim(), "" },
|
||||
{ "\t \t ".trim(), "" },
|
||||
{ "\t A B C\t ".trim(), "A B C" },
|
||||
{ " \t A B C \t".trim(), "A B C" },
|
||||
{ "\t \uFF21 \uFF22 \uFF23\t ".trim(), "\uFF21 \uFF22 \uFF23" },
|
||||
{ " \t \uFF21 \uFF22 \uFF23 \t".trim(), "\uFF21 \uFF22 \uFF23" },
|
||||
{ " \t \uFF41 \uFF42 \uFF43 \t".trim(), "\uFF41 \uFF42 \uFF43" },
|
||||
{ " \t A\uFF21 B\uFF22 C\uFF23 \t".trim(),
|
||||
"A\uFF21 B\uFF22 C\uFF23" } };
|
||||
}
|
||||
|
||||
/*
|
||||
* test trim().
|
||||
*
|
||||
* @param res
|
||||
* real result
|
||||
* @param expected
|
||||
* expected result
|
||||
*/
|
||||
@Test(dataProvider = "trims")
|
||||
public void testTrim(String res, String expected) {
|
||||
assertEquals(res, expected);
|
||||
}
|
||||
|
||||
}
|
92
jdk/test/java/lang/String/CompactString/VMOptionsTest.java
Normal file
92
jdk/test/java/lang/String/CompactString/VMOptionsTest.java
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8077559
|
||||
* @summary Tests Compact String. This one is testing
|
||||
* if Compact String enable/disable VM Options is indeed working in String class,
|
||||
* it's verified by testing if the VM option affect coder and
|
||||
* COMPACT_STRINGS field in String class.
|
||||
* @run testng/othervm -XX:+CompactStrings -DCompactStringEnabled=true VMOptionsTest
|
||||
* @run testng/othervm -XX:-CompactStrings -DCompactStringEnabled=false VMOptionsTest
|
||||
* @run testng/othervm -DCompactStringEnabled=true VMOptionsTest
|
||||
*/
|
||||
|
||||
public class VMOptionsTest {
|
||||
boolean compactStringEnabled;
|
||||
// corresponding "COMPACT_STRINGS" field in String class.
|
||||
Field COMPACT_STRINGS;
|
||||
// corresponding "coder" field in String class.
|
||||
Field coder;
|
||||
|
||||
// corresponding coder type in String class.
|
||||
final byte LATIN1 = 0;
|
||||
final byte UTF16 = 1;
|
||||
|
||||
@BeforeClass
|
||||
public void setUp() throws Exception {
|
||||
compactStringEnabled = Boolean.valueOf(System.getProperty("CompactStringEnabled", null));
|
||||
COMPACT_STRINGS = String.class.getDeclaredField("COMPACT_STRINGS");
|
||||
COMPACT_STRINGS.setAccessible(true);
|
||||
coder = String.class.getDeclaredField("coder");
|
||||
coder.setAccessible(true);
|
||||
}
|
||||
|
||||
@DataProvider
|
||||
public Object[][] provider() {
|
||||
return new Object[][] {
|
||||
new Object[] {"", LATIN1},
|
||||
new Object[] {"abc", LATIN1},
|
||||
new Object[] {"A\uff21", UTF16},
|
||||
new Object[] {"\uff21\uff22", UTF16}
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* verify the coder field in String objects.
|
||||
*/
|
||||
@Test(dataProvider = "provider")
|
||||
public void testCoder(String str, byte expected) throws Exception {
|
||||
byte c = (byte) coder.get(str);
|
||||
expected = compactStringEnabled ? expected : UTF16;
|
||||
assertEquals(c, expected);
|
||||
}
|
||||
|
||||
/*
|
||||
* verify the COMPACT_STRINGS flag in String objects.
|
||||
*/
|
||||
@Test(dataProvider = "provider")
|
||||
public void testCompactStringFlag(String str, byte ignore) throws Exception {
|
||||
assertTrue(COMPACT_STRINGS.get(str).equals(compactStringEnabled));
|
||||
}
|
||||
}
|
78
jdk/test/java/lang/String/CompactString/ValueOf.java
Normal file
78
jdk/test/java/lang/String/CompactString/ValueOf.java
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8077559
|
||||
* @summary Tests Compact String. This one is for String.valueOf.
|
||||
* valueOf(char[] data) is not tested here.
|
||||
* @run testng/othervm -XX:+CompactStrings ValueOf
|
||||
* @run testng/othervm -XX:-CompactStrings ValueOf
|
||||
*/
|
||||
|
||||
public class ValueOf {
|
||||
|
||||
/*
|
||||
* Data provider for testValueOf
|
||||
*
|
||||
* @return input parameter for testValueOf
|
||||
*/
|
||||
@DataProvider
|
||||
public Object[][] valueOfs() {
|
||||
return new Object[][] { { String.valueOf(true), "true" },
|
||||
{ String.valueOf(false), "false" },
|
||||
{ String.valueOf(1.0f), "1.0" },
|
||||
{ String.valueOf(0.0f), "0.0" },
|
||||
{ String.valueOf(Float.MAX_VALUE), "3.4028235E38" },
|
||||
{ String.valueOf(Float.MIN_VALUE), "1.4E-45" },
|
||||
{ String.valueOf(1.0d), "1.0" },
|
||||
{ String.valueOf(0.0d), "0.0" },
|
||||
{ String.valueOf(Double.MAX_VALUE), "1.7976931348623157E308" },
|
||||
{ String.valueOf(Double.MIN_VALUE), "4.9E-324" },
|
||||
{ String.valueOf(1), "1" }, { String.valueOf(0), "0" },
|
||||
{ String.valueOf(Integer.MAX_VALUE), "2147483647" },
|
||||
{ String.valueOf(Integer.MIN_VALUE), "-2147483648" },
|
||||
{ String.valueOf(1L), "1" }, { String.valueOf(0L), "0" },
|
||||
{ String.valueOf(Long.MAX_VALUE), "9223372036854775807" },
|
||||
{ String.valueOf(Long.MIN_VALUE), "-9223372036854775808" } };
|
||||
}
|
||||
|
||||
/*
|
||||
* test String.valueOf(xxx).
|
||||
*
|
||||
* @param res
|
||||
* real result
|
||||
* @param expected
|
||||
* expected result
|
||||
*/
|
||||
@Test(dataProvider = "valueOfs")
|
||||
public void testValueOf(String res, String expected) {
|
||||
assertEquals(res, expected);
|
||||
}
|
||||
|
||||
}
|
@ -22,7 +22,7 @@
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 8058779
|
||||
* @bug 8058779 8054307
|
||||
* @library /lib/testlibrary/
|
||||
* @build jdk.testlibrary.RandomFactory
|
||||
* @run testng LiteralReplace
|
||||
@ -104,6 +104,109 @@ public class LiteralReplace {
|
||||
{"abcdefgh", "[a-h]", "X", "abcdefgh"},
|
||||
{"aa+", "a+", "", "a"},
|
||||
{"^abc$", "abc", "x", "^x$"},
|
||||
|
||||
// more with non-latin1 characters
|
||||
{"\u4e00\u4e00\u4e00",
|
||||
"\u4e00\u4e00",
|
||||
"\u4e01",
|
||||
"\u4e01\u4e00"},
|
||||
|
||||
{"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05\u4e06\u4e07\u4e08",
|
||||
"\u4e03\u4e04\u4e05",
|
||||
"\u4e10\u4e11\u4e12",
|
||||
"\u4e00\u4e01\u4e02\u4e10\u4e11\u4e12\u4e06\u4e07\u4e08"},
|
||||
|
||||
{"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05\u4e06\u4e07\u4e08",
|
||||
"ABC",
|
||||
"\u4e10\u4e11\u4e12",
|
||||
"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05\u4e06\u4e07\u4e08"},
|
||||
|
||||
{"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e02\u4e03\u4e07\u4e08",
|
||||
"\u4e02\u4e03",
|
||||
"\u4e12\u4e13",
|
||||
"\u4e00\u4e01\u4e12\u4e13\u4e04\u4e12\u4e13\u4e07\u4e08"},
|
||||
|
||||
{"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e02\u4e03\u4e07\u4e08",
|
||||
"\u4e02\u4e03",
|
||||
"ab",
|
||||
"\u4e00\u4e01ab\u4e04ab\u4e07\u4e08"},
|
||||
|
||||
{"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05\u4e06\u4e07",
|
||||
"",
|
||||
"_",
|
||||
"_\u4e00_\u4e01_\u4e02_\u4e03_\u4e04_\u4e05_\u4e06_\u4e07_"},
|
||||
{"^\u4e00\u4e01\u4e02$",
|
||||
"\u4e00\u4e01\u4e02",
|
||||
"\u4e03",
|
||||
"^\u4e03$"},
|
||||
|
||||
{"", "\u4e00", "\u4e01", ""},
|
||||
{"", "", "\u4e00\u4e01\u4e02", "\u4e00\u4e01\u4e02"},
|
||||
|
||||
{"^\u4e00\u4e01\u4e02$",
|
||||
"\u4e00\u4e01\u4e02",
|
||||
"X",
|
||||
"^X$"},
|
||||
|
||||
{"abcdefgh",
|
||||
"def",
|
||||
"\u4e01",
|
||||
"abc\u4e01gh"},
|
||||
|
||||
{"abcdefgh",
|
||||
"def",
|
||||
"\u4e01\u4e02",
|
||||
"abc\u4e01\u4e02gh"},
|
||||
|
||||
{"abcdefabcgh",
|
||||
"abc",
|
||||
"\u4e01\u4e02",
|
||||
"\u4e01\u4e02def\u4e01\u4e02gh"},
|
||||
|
||||
{"abcdefabcghabc",
|
||||
"abc",
|
||||
"\u4e01\u4e02",
|
||||
"\u4e01\u4e02def\u4e01\u4e02gh\u4e01\u4e02"},
|
||||
|
||||
{"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05",
|
||||
"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05",
|
||||
"abcd",
|
||||
"abcd"},
|
||||
|
||||
{"\u4e00\u4e01",
|
||||
"\u4e00\u4e01",
|
||||
"abcdefg",
|
||||
"abcdefg"},
|
||||
|
||||
{"\u4e00\u4e01xyz",
|
||||
"\u4e00\u4e01",
|
||||
"abcdefg",
|
||||
"abcdefgxyz"},
|
||||
|
||||
{"\u4e00\u4e00\u4e00\u4e00\u4e00\u4e00",
|
||||
"\u4e00\u4e00",
|
||||
"\u4e00\u4e00\u4e00",
|
||||
"\u4e00\u4e00\u4e00\u4e00\u4e00\u4e00\u4e00\u4e00\u4e00"},
|
||||
|
||||
{"\u4e00\u4e00\u4e00\u4e00\u4e00\u4e00",
|
||||
"\u4e00\u4e00\u4e00",
|
||||
"\u4e00\u4e00",
|
||||
"\u4e00\u4e00\u4e00\u4e00"},
|
||||
|
||||
{"\u4e00.\u4e01.\u4e02.\u4e03.\u4e04.",
|
||||
".",
|
||||
"-",
|
||||
"\u4e00-\u4e01-\u4e02-\u4e03-\u4e04-"},
|
||||
|
||||
{"\u4e00\u4e00\u4e00\u4e00\u4e00\u4e00",
|
||||
"\u4e00",
|
||||
"",
|
||||
""},
|
||||
|
||||
{"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05",
|
||||
"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05",
|
||||
"",
|
||||
""},
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
@test
|
||||
@bug 4217441 4533872 4900935 8020037 8032012 8041791 8042589
|
||||
@bug 4217441 4533872 4900935 8020037 8032012 8041791 8042589 8054307
|
||||
@summary toLowerCase should lower-case Greek Sigma correctly depending
|
||||
on the context (final/non-final). Also it should handle
|
||||
Locale specific (lt, tr, and az) lowercasings and supplementary
|
||||
@ -134,14 +134,60 @@ public class ToLowerCase {
|
||||
}
|
||||
test(src.toString(), Locale.US, exp.toString());
|
||||
|
||||
// test latin1
|
||||
src = new StringBuilder(0x100);
|
||||
exp = new StringBuilder(0x100);
|
||||
for (int cp = 0; cp < 0x100; cp++) {
|
||||
int lowerCase = Character.toLowerCase(cp);
|
||||
if (lowerCase == -1) { //Character.ERROR
|
||||
continue;
|
||||
}
|
||||
src.appendCodePoint(cp);
|
||||
exp.appendCodePoint(lowerCase);
|
||||
}
|
||||
test(src.toString(), Locale.US, exp.toString());
|
||||
|
||||
// test non-latin1 -> latin1
|
||||
src = new StringBuilder(0x100).append("abc");
|
||||
exp = new StringBuilder(0x100).append("abc");
|
||||
for (int cp = 0x100; cp < 0x10000; cp++) {
|
||||
int lowerCase = Character.toLowerCase(cp);
|
||||
if (lowerCase < 0x100 && cp != '\u0130') {
|
||||
src.appendCodePoint(cp);
|
||||
exp.appendCodePoint(lowerCase);
|
||||
}
|
||||
}
|
||||
test(src.toString(), Locale.US, exp.toString());
|
||||
}
|
||||
|
||||
static void test(String in, Locale locale, String expected) {
|
||||
test0(in, locale,expected);
|
||||
for (String[] ss : new String[][] {
|
||||
new String[] {"abc", "abc"},
|
||||
new String[] {"aBc", "abc"},
|
||||
new String[] {"ABC", "abc"},
|
||||
new String[] {"ab\u4e00", "ab\u4e00"},
|
||||
new String[] {"aB\u4e00", "ab\u4e00"},
|
||||
new String[] {"AB\u4e00", "ab\u4e00"},
|
||||
new String[] {"ab\uD800\uDC00", "ab\uD800\uDC00"},
|
||||
new String[] {"aB\uD800\uDC00", "ab\uD800\uDC00"},
|
||||
new String[] {"AB\uD800\uDC00", "ab\uD800\uDC00"},
|
||||
new String[] {"ab\uD801\uDC1C", "ab\uD801\uDC44"},
|
||||
new String[] {"aB\uD801\uDC1C", "ab\uD801\uDC44"},
|
||||
new String[] {"AB\uD801\uDC1C", "ab\uD801\uDC44"},
|
||||
|
||||
}) {
|
||||
test0(ss[0] + " " + in, locale, ss[1] + " " + expected);
|
||||
test0(in + " " + ss[0], locale, expected + " " + ss[1]);
|
||||
}
|
||||
}
|
||||
|
||||
static void test0(String in, Locale locale, String expected) {
|
||||
String result = in.toLowerCase(locale);
|
||||
if (!result.equals(expected)) {
|
||||
System.err.println("input: " + in + ", locale: " + locale +
|
||||
", expected: " + expected + ", actual: " + result);
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
@test
|
||||
@bug 4219630 4304573 4533872 4900935 8042589
|
||||
@bug 4219630 4304573 4533872 4900935 8042589 8054307
|
||||
@summary toUpperCase should upper-case German sharp s correctly even if
|
||||
it's the only character in the string. should also uppercase
|
||||
all of the 1:M char mappings correctly. Also it should handle
|
||||
@ -97,14 +97,66 @@ public class ToUpperCase {
|
||||
test("A\uD801\uDC44", Locale.ROOT, "A\uD801\uDC1c");
|
||||
test("a\uD801\uDC28\uD801\uDC29\uD801\uDC2A", Locale.US, "A\uD801\uDC00\uD801\uDC01\uD801\uDC02");
|
||||
test("A\uD801\uDC28a\uD801\uDC29b\uD801\uDC2Ac", Locale.US, "A\uD801\uDC00A\uD801\uDC01B\uD801\uDC02C");
|
||||
|
||||
// test latin1 only case
|
||||
StringBuilder src = new StringBuilder(0x100);
|
||||
StringBuilder exp = new StringBuilder(0x100);
|
||||
for (int cp = 0; cp < 0x100; cp++) {
|
||||
int upperCase = Character.toUpperCase(cp);
|
||||
if (upperCase == -1) { //Character.ERROR
|
||||
continue;
|
||||
}
|
||||
src.appendCodePoint(cp);
|
||||
if (cp == '\u00df') {
|
||||
exp.append("SS"); // need Character.toUpperCaseEx()
|
||||
} else {
|
||||
exp.appendCodePoint(upperCase);
|
||||
}
|
||||
}
|
||||
test(src.toString(), Locale.US, exp.toString());
|
||||
|
||||
// test non-latin1 -> latin1
|
||||
src = new StringBuilder(0x100).append("ABC");
|
||||
exp = new StringBuilder(0x100).append("ABC");
|
||||
for (int cp = 0x100; cp < 0x10000; cp++) {
|
||||
int upperCase = Character.toUpperCase(cp);
|
||||
if (upperCase < 0x100) {
|
||||
src.appendCodePoint(cp);
|
||||
exp.appendCodePoint(upperCase);
|
||||
}
|
||||
}
|
||||
test(src.toString(), Locale.US, exp.toString());
|
||||
|
||||
}
|
||||
|
||||
static void test(String in, Locale locale, String expected) {
|
||||
test0(in, locale,expected);
|
||||
// trigger different code paths
|
||||
for (String[] ss : new String[][] {
|
||||
new String[] {"abc", "ABC"},
|
||||
new String[] {"AbC", "ABC"},
|
||||
new String[] {"ABC", "ABC"},
|
||||
new String[] {"AB\u4e00", "AB\u4e00"},
|
||||
new String[] {"ab\u4e00", "AB\u4e00"},
|
||||
new String[] {"aB\u4e00", "AB\u4e00"},
|
||||
new String[] {"AB\uD800\uDC00", "AB\uD800\uDC00"},
|
||||
new String[] {"Ab\uD800\uDC00", "AB\uD800\uDC00"},
|
||||
new String[] {"ab\uD800\uDC00", "AB\uD800\uDC00"},
|
||||
new String[] {"AB\uD801\uDC44", "AB\uD801\uDC1C"},
|
||||
new String[] {"Ab\uD801\uDC44", "AB\uD801\uDC1C"},
|
||||
new String[] {"ab\uD801\uDC44", "AB\uD801\uDC1C"},
|
||||
}) {
|
||||
test0(ss[0] + " " + in, locale, ss[1] + " " + expected);
|
||||
test0(in + " " + ss[0], locale, expected + " " + ss[1]);
|
||||
}
|
||||
}
|
||||
|
||||
static void test0(String in, Locale locale, String expected) {
|
||||
String result = in.toUpperCase(locale);
|
||||
if (!result.equals(expected)) {
|
||||
System.err.println("input: " + in + ", locale: " + locale +
|
||||
", expected: " + expected + ", actual: " + result);
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
489
jdk/test/java/lang/StringBuffer/CompactStringBuffer.java
Normal file
489
jdk/test/java/lang/StringBuffer/CompactStringBuffer.java
Normal file
@ -0,0 +1,489 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8077559
|
||||
* @summary Tests Compact String. This test is testing StringBuffer
|
||||
* behavior related to Compact String.
|
||||
* @run testng/othervm -XX:+CompactStrings CompactStringBuffer
|
||||
* @run testng/othervm -XX:-CompactStrings CompactStringBuffer
|
||||
*/
|
||||
|
||||
public class CompactStringBuffer {
|
||||
|
||||
/*
|
||||
* Tests for "A"
|
||||
*/
|
||||
@Test
|
||||
public void testCompactStringBufferForLatinA() {
|
||||
final String ORIGIN = "A";
|
||||
/*
|
||||
* Because right now ASCII is the default encoding parameter for source
|
||||
* code in JDK build environment, so we escape them. same as below.
|
||||
*/
|
||||
check(new StringBuffer(ORIGIN).append(new char[] { '\uFF21' }),
|
||||
"A\uFF21");
|
||||
check(new StringBuffer(ORIGIN).append(new StringBuffer("\uFF21")),
|
||||
"A\uFF21");
|
||||
check(new StringBuffer(ORIGIN).append("\uFF21"), "A\uFF21");
|
||||
check(new StringBuffer(ORIGIN).append(new StringBuffer("\uFF21")),
|
||||
"A\uFF21");
|
||||
check(new StringBuffer(ORIGIN).delete(0, 1), "");
|
||||
check(new StringBuffer(ORIGIN).delete(0, 0), "A");
|
||||
check(new StringBuffer(ORIGIN).deleteCharAt(0), "");
|
||||
assertEquals(new StringBuffer(ORIGIN).indexOf("A", 0), 0);
|
||||
assertEquals(new StringBuffer(ORIGIN).indexOf("\uFF21", 0), -1);
|
||||
assertEquals(new StringBuffer(ORIGIN).indexOf("", 0), 0);
|
||||
assertEquals(new StringBuffer(ORIGIN).insert(1, "\uD801\uDC00")
|
||||
.indexOf("A", 0), 0);
|
||||
assertEquals(new StringBuffer(ORIGIN).insert(0, "\uD801\uDC00")
|
||||
.indexOf("A", 0), 2);
|
||||
check(new StringBuffer(ORIGIN).insert(0, new char[] {}), "A");
|
||||
check(new StringBuffer(ORIGIN).insert(1, new char[] { '\uFF21' }),
|
||||
"A\uFF21");
|
||||
check(new StringBuffer(ORIGIN).insert(0, new char[] { '\uFF21' }),
|
||||
"\uFF21A");
|
||||
check(new StringBuffer(ORIGIN).insert(0, new StringBuffer("\uFF21")),
|
||||
"\uFF21A");
|
||||
check(new StringBuffer(ORIGIN).insert(1, new StringBuffer("\uFF21")),
|
||||
"A\uFF21");
|
||||
check(new StringBuffer(ORIGIN).insert(0, ""), "A");
|
||||
check(new StringBuffer(ORIGIN).insert(0, "\uFF21"), "\uFF21A");
|
||||
check(new StringBuffer(ORIGIN).insert(1, "\uFF21"), "A\uFF21");
|
||||
assertEquals(new StringBuffer(ORIGIN).lastIndexOf("A"), 0);
|
||||
assertEquals(new StringBuffer(ORIGIN).lastIndexOf("\uFF21"), -1);
|
||||
assertEquals(new StringBuffer(ORIGIN).lastIndexOf(""), 1);
|
||||
check(new StringBuffer(ORIGIN).replace(0, 0, "\uFF21"), "\uFF21A");
|
||||
check(new StringBuffer(ORIGIN).replace(0, 1, "\uFF21"), "\uFF21");
|
||||
checkSetCharAt(new StringBuffer(ORIGIN), 0, '\uFF21', "\uFF21");
|
||||
checkSetLength(new StringBuffer(ORIGIN), 0, "");
|
||||
checkSetLength(new StringBuffer(ORIGIN), 1, "A");
|
||||
check(new StringBuffer(ORIGIN).substring(0), "A");
|
||||
check(new StringBuffer(ORIGIN).substring(1), "");
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests for "\uFF21"
|
||||
*/
|
||||
@Test
|
||||
public void testCompactStringBufferForNonLatinA() {
|
||||
final String ORIGIN = "\uFF21";
|
||||
check(new StringBuffer(ORIGIN).append(new char[] { 'A' }), "\uFF21A");
|
||||
check(new StringBuffer(ORIGIN).append(new StringBuffer("A")), "\uFF21A");
|
||||
check(new StringBuffer(ORIGIN).append("A"), "\uFF21A");
|
||||
check(new StringBuffer(ORIGIN).append(new StringBuffer("A")), "\uFF21A");
|
||||
check(new StringBuffer(ORIGIN).delete(0, 1), "");
|
||||
check(new StringBuffer(ORIGIN).delete(0, 0), "\uFF21");
|
||||
check(new StringBuffer(ORIGIN).deleteCharAt(0), "");
|
||||
assertEquals(new StringBuffer(ORIGIN).indexOf("A", 0), -1);
|
||||
assertEquals(new StringBuffer(ORIGIN).indexOf("\uFF21", 0), 0);
|
||||
assertEquals(new StringBuffer(ORIGIN).indexOf("", 0), 0);
|
||||
check(new StringBuffer(ORIGIN).insert(0, new char[] {}), "\uFF21");
|
||||
check(new StringBuffer(ORIGIN).insert(1, new char[] { 'A' }), "\uFF21A");
|
||||
check(new StringBuffer(ORIGIN).insert(0, new char[] { 'A' }), "A\uFF21");
|
||||
check(new StringBuffer(ORIGIN).insert(0, new StringBuffer("A")),
|
||||
"A\uFF21");
|
||||
check(new StringBuffer(ORIGIN).insert(1, new StringBuffer("A")),
|
||||
"\uFF21A");
|
||||
check(new StringBuffer(ORIGIN).insert(0, ""), "\uFF21");
|
||||
check(new StringBuffer(ORIGIN).insert(0, "A"), "A\uFF21");
|
||||
check(new StringBuffer(ORIGIN).insert(1, "A"), "\uFF21A");
|
||||
assertEquals(new StringBuffer(ORIGIN).lastIndexOf("A"), -1);
|
||||
assertEquals(new StringBuffer(ORIGIN).lastIndexOf("\uFF21"), 0);
|
||||
assertEquals(new StringBuffer(ORIGIN).lastIndexOf(""), 1);
|
||||
check(new StringBuffer(ORIGIN).replace(0, 0, "A"), "A\uFF21");
|
||||
check(new StringBuffer(ORIGIN).replace(0, 1, "A"), "A");
|
||||
checkSetCharAt(new StringBuffer(ORIGIN), 0, 'A', "A");
|
||||
checkSetLength(new StringBuffer(ORIGIN), 0, "");
|
||||
checkSetLength(new StringBuffer(ORIGIN), 1, "\uFF21");
|
||||
check(new StringBuffer(ORIGIN).substring(0), "\uFF21");
|
||||
check(new StringBuffer(ORIGIN).substring(1), "");
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests for "\uFF21A"
|
||||
*/
|
||||
@Test
|
||||
public void testCompactStringBufferForMixedA1() {
|
||||
final String ORIGIN = "\uFF21A";
|
||||
check(new StringBuffer(ORIGIN).delete(0, 1), "A");
|
||||
check(new StringBuffer(ORIGIN).delete(1, 2), "\uFF21");
|
||||
check(new StringBuffer(ORIGIN).deleteCharAt(1), "\uFF21");
|
||||
check(new StringBuffer(ORIGIN).deleteCharAt(0), "A");
|
||||
assertEquals(new StringBuffer(ORIGIN).indexOf("A", 0), 1);
|
||||
assertEquals(new StringBuffer(ORIGIN).indexOf("\uFF21", 0), 0);
|
||||
assertEquals(new StringBuffer(ORIGIN).indexOf("", 0), 0);
|
||||
check(new StringBuffer(ORIGIN).insert(1, new char[] { 'A' }), "\uFF21AA");
|
||||
check(new StringBuffer(ORIGIN).insert(0, new char[] { '\uFF21' }),
|
||||
"\uFF21\uFF21A");
|
||||
assertEquals(new StringBuffer(ORIGIN).lastIndexOf("A"), 1);
|
||||
assertEquals(new StringBuffer(ORIGIN).lastIndexOf("\uFF21"), 0);
|
||||
assertEquals(new StringBuffer(ORIGIN).lastIndexOf(""), 2);
|
||||
check(new StringBuffer(ORIGIN).replace(0, 0, "A"), "A\uFF21A");
|
||||
check(new StringBuffer(ORIGIN).replace(0, 1, "A"), "AA");
|
||||
checkSetCharAt(new StringBuffer(ORIGIN), 0, 'A', "AA");
|
||||
checkSetLength(new StringBuffer(ORIGIN), 0, "");
|
||||
checkSetLength(new StringBuffer(ORIGIN), 1, "\uFF21");
|
||||
check(new StringBuffer(ORIGIN).substring(0), "\uFF21A");
|
||||
check(new StringBuffer(ORIGIN).substring(1), "A");
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests for "A\uFF21"
|
||||
*/
|
||||
@Test
|
||||
public void testCompactStringBufferForMixedA2() {
|
||||
final String ORIGIN = "A\uFF21";
|
||||
check(new StringBuffer(ORIGIN).replace(1, 2, "A"), "AA");
|
||||
checkSetLength(new StringBuffer(ORIGIN), 1, "A");
|
||||
check(new StringBuffer(ORIGIN).substring(0), "A\uFF21");
|
||||
check(new StringBuffer(ORIGIN).substring(1), "\uFF21");
|
||||
check(new StringBuffer(ORIGIN).substring(0, 1), "A");
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests for "\uFF21A\uFF21A\uFF21A\uFF21A\uFF21A"
|
||||
*/
|
||||
@Test
|
||||
public void testCompactStringBufferForDuplicatedMixedA1() {
|
||||
final String ORIGIN = "\uFF21A\uFF21A\uFF21A\uFF21A\uFF21A";
|
||||
checkSetLength(new StringBuffer(ORIGIN), 1, "\uFF21");
|
||||
assertEquals(new StringBuffer(ORIGIN).indexOf("A", 5), 5);
|
||||
assertEquals(new StringBuffer(ORIGIN).indexOf("\uFF21", 5), 6);
|
||||
assertEquals(new StringBuffer(ORIGIN).lastIndexOf("A"), 9);
|
||||
assertEquals(new StringBuffer(ORIGIN).lastIndexOf("\uFF21"), 8);
|
||||
assertEquals(new StringBuffer(ORIGIN).lastIndexOf(""), 10);
|
||||
check(new StringBuffer(ORIGIN).substring(9), "A");
|
||||
check(new StringBuffer(ORIGIN).substring(8), "\uFF21A");
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests for "A\uFF21A\uFF21A\uFF21A\uFF21A\uFF21"
|
||||
*/
|
||||
@Test
|
||||
public void testCompactStringBufferForDuplicatedMixedA2() {
|
||||
final String ORIGIN = "A\uFF21A\uFF21A\uFF21A\uFF21A\uFF21";
|
||||
checkSetLength(new StringBuffer(ORIGIN), 1, "A");
|
||||
assertEquals(new StringBuffer(ORIGIN).indexOf("A", 5), 6);
|
||||
assertEquals(new StringBuffer(ORIGIN).indexOf("\uFF21", 5), 5);
|
||||
assertEquals(new StringBuffer(ORIGIN).lastIndexOf("A"), 8);
|
||||
assertEquals(new StringBuffer(ORIGIN).lastIndexOf("\uFF21"), 9);
|
||||
check(new StringBuffer(ORIGIN).substring(9), "\uFF21");
|
||||
check(new StringBuffer(ORIGIN).substring(8), "A\uFF21");
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests for "\uD801\uDC00\uD801\uDC01"
|
||||
*/
|
||||
@Test
|
||||
public void testCompactStringForSupplementaryCodePoint() {
|
||||
final String ORIGIN = "\uD801\uDC00\uD801\uDC01";
|
||||
check(new StringBuffer(ORIGIN).append("A"), "\uD801\uDC00\uD801\uDC01A");
|
||||
check(new StringBuffer(ORIGIN).append("\uFF21"),
|
||||
"\uD801\uDC00\uD801\uDC01\uFF21");
|
||||
check(new StringBuffer(ORIGIN).appendCodePoint('A'),
|
||||
"\uD801\uDC00\uD801\uDC01A");
|
||||
check(new StringBuffer(ORIGIN).appendCodePoint('\uFF21'),
|
||||
"\uD801\uDC00\uD801\uDC01\uFF21");
|
||||
assertEquals(new StringBuffer(ORIGIN).charAt(0), '\uD801');
|
||||
assertEquals(new StringBuffer(ORIGIN).codePointAt(0),
|
||||
Character.codePointAt(ORIGIN, 0));
|
||||
assertEquals(new StringBuffer(ORIGIN).codePointAt(1),
|
||||
Character.codePointAt(ORIGIN, 1));
|
||||
assertEquals(new StringBuffer(ORIGIN).codePointBefore(2),
|
||||
Character.codePointAt(ORIGIN, 0));
|
||||
assertEquals(new StringBuffer(ORIGIN).codePointCount(1, 3), 2);
|
||||
check(new StringBuffer(ORIGIN).delete(0, 2), "\uD801\uDC01");
|
||||
check(new StringBuffer(ORIGIN).delete(0, 3), "\uDC01");
|
||||
check(new StringBuffer(ORIGIN).deleteCharAt(1), "\uD801\uD801\uDC01");
|
||||
checkGetChars(new StringBuffer(ORIGIN), 0, 3, new char[] { '\uD801',
|
||||
'\uDC00', '\uD801' });
|
||||
assertEquals(new StringBuffer(ORIGIN).indexOf("\uD801\uDC01"), 2);
|
||||
assertEquals(new StringBuffer(ORIGIN).indexOf("\uDC01"), 3);
|
||||
assertEquals(new StringBuffer(ORIGIN).indexOf("\uFF21"), -1);
|
||||
assertEquals(new StringBuffer(ORIGIN).indexOf("A"), -1);
|
||||
check(new StringBuffer(ORIGIN).insert(0, "\uFF21"),
|
||||
"\uFF21\uD801\uDC00\uD801\uDC01");
|
||||
check(new StringBuffer(ORIGIN).insert(1, "\uFF21"),
|
||||
"\uD801\uFF21\uDC00\uD801\uDC01");
|
||||
check(new StringBuffer(ORIGIN).insert(1, "A"),
|
||||
"\uD801A\uDC00\uD801\uDC01");
|
||||
assertEquals(new StringBuffer(ORIGIN).lastIndexOf("\uDC00\uD801"), 1);
|
||||
assertEquals(new StringBuffer(ORIGIN).lastIndexOf("\uD801"), 2);
|
||||
assertEquals(new StringBuffer(ORIGIN).lastIndexOf("\uFF21"), -1);
|
||||
assertEquals(new StringBuffer(ORIGIN).lastIndexOf("A"), -1);
|
||||
assertEquals(new StringBuffer(ORIGIN).length(), 4);
|
||||
assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(1, 1), 2);
|
||||
assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(0, 1), 2);
|
||||
check(new StringBuffer(ORIGIN).replace(0, 2, "A"), "A\uD801\uDC01");
|
||||
check(new StringBuffer(ORIGIN).replace(0, 3, "A"), "A\uDC01");
|
||||
check(new StringBuffer(ORIGIN).replace(0, 2, "\uFF21"),
|
||||
"\uFF21\uD801\uDC01");
|
||||
check(new StringBuffer(ORIGIN).replace(0, 3, "\uFF21"), "\uFF21\uDC01");
|
||||
check(new StringBuffer(ORIGIN).reverse(), "\uD801\uDC01\uD801\uDC00");
|
||||
checkSetCharAt(new StringBuffer(ORIGIN), 1, '\uDC01',
|
||||
"\uD801\uDC01\uD801\uDC01");
|
||||
checkSetCharAt(new StringBuffer(ORIGIN), 1, 'A', "\uD801A\uD801\uDC01");
|
||||
checkSetLength(new StringBuffer(ORIGIN), 2, "\uD801\uDC00");
|
||||
checkSetLength(new StringBuffer(ORIGIN), 3, "\uD801\uDC00\uD801");
|
||||
check(new StringBuffer(ORIGIN).substring(1, 3), "\uDC00\uD801");
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests for "A\uD801\uDC00\uFF21"
|
||||
*/
|
||||
@Test
|
||||
public void testCompactStringForSupplementaryCodePointMixed1() {
|
||||
final String ORIGIN = "A\uD801\uDC00\uFF21";
|
||||
assertEquals(new StringBuffer(ORIGIN).codePointBefore(3),
|
||||
Character.codePointAt(ORIGIN, 1));
|
||||
assertEquals(new StringBuffer(ORIGIN).codePointBefore(2), '\uD801');
|
||||
assertEquals(new StringBuffer(ORIGIN).codePointBefore(1), 'A');
|
||||
assertEquals(new StringBuffer(ORIGIN).codePointCount(0, 3), 2);
|
||||
assertEquals(new StringBuffer(ORIGIN).codePointCount(0, 4), 3);
|
||||
check(new StringBuffer(ORIGIN).delete(0, 1), "\uD801\uDC00\uFF21");
|
||||
check(new StringBuffer(ORIGIN).delete(0, 1).delete(2, 3), "\uD801\uDC00");
|
||||
check(new StringBuffer(ORIGIN).deleteCharAt(3).deleteCharAt(0),
|
||||
"\uD801\uDC00");
|
||||
assertEquals(new StringBuffer(ORIGIN).indexOf("\uFF21"), 3);
|
||||
assertEquals(new StringBuffer(ORIGIN).indexOf("A"), 0);
|
||||
assertEquals(new StringBuffer(ORIGIN).lastIndexOf("\uFF21"), 3);
|
||||
assertEquals(new StringBuffer(ORIGIN).lastIndexOf("A"), 0);
|
||||
assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(0, 1), 1);
|
||||
assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(1, 1), 3);
|
||||
check(new StringBuffer(ORIGIN).replace(1, 3, "A"), "AA\uFF21");
|
||||
check(new StringBuffer(ORIGIN).replace(1, 4, "A"), "AA");
|
||||
check(new StringBuffer(ORIGIN).replace(1, 4, ""), "A");
|
||||
check(new StringBuffer(ORIGIN).reverse(), "\uFF21\uD801\uDC00A");
|
||||
checkSetLength(new StringBuffer(ORIGIN), 1, "A");
|
||||
check(new StringBuffer(ORIGIN).substring(0, 1), "A");
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests for "\uD801\uDC00\uFF21A"
|
||||
*/
|
||||
@Test
|
||||
public void testCompactStringForSupplementaryCodePointMixed2() {
|
||||
final String ORIGIN = "\uD801\uDC00\uFF21A";
|
||||
assertEquals(new StringBuffer(ORIGIN).codePointBefore(3),
|
||||
Character.codePointAt(ORIGIN, 2));
|
||||
assertEquals(new StringBuffer(ORIGIN).codePointBefore(2),
|
||||
Character.codePointAt(ORIGIN, 0));
|
||||
assertEquals(new StringBuffer(ORIGIN).codePointBefore(1), '\uD801');
|
||||
assertEquals(new StringBuffer(ORIGIN).codePointCount(0, 3), 2);
|
||||
assertEquals(new StringBuffer(ORIGIN).codePointCount(0, 4), 3);
|
||||
check(new StringBuffer(ORIGIN).delete(0, 2), "\uFF21A");
|
||||
check(new StringBuffer(ORIGIN).delete(0, 3), "A");
|
||||
check(new StringBuffer(ORIGIN).deleteCharAt(0).deleteCharAt(0)
|
||||
.deleteCharAt(0), "A");
|
||||
assertEquals(new StringBuffer(ORIGIN).indexOf("A"), 3);
|
||||
assertEquals(new StringBuffer(ORIGIN).delete(0, 3).indexOf("A"), 0);
|
||||
assertEquals(new StringBuffer(ORIGIN).replace(0, 3, "B").indexOf("A"),
|
||||
1);
|
||||
assertEquals(new StringBuffer(ORIGIN).substring(3, 4).indexOf("A"), 0);
|
||||
assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(1, 1), 2);
|
||||
assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(0, 1), 2);
|
||||
assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(2, 1), 3);
|
||||
check(new StringBuffer(ORIGIN).replace(0, 3, "B"), "BA");
|
||||
check(new StringBuffer(ORIGIN).reverse(), "A\uFF21\uD801\uDC00");
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests for "\uD801A\uDC00\uFF21"
|
||||
*/
|
||||
@Test
|
||||
public void testCompactStringForSupplementaryCodePointMixed3() {
|
||||
final String ORIGIN = "\uD801A\uDC00\uFF21";
|
||||
assertEquals(new StringBuffer(ORIGIN).codePointAt(1), 'A');
|
||||
assertEquals(new StringBuffer(ORIGIN).codePointAt(3), '\uFF21');
|
||||
assertEquals(new StringBuffer(ORIGIN).codePointBefore(1), '\uD801');
|
||||
assertEquals(new StringBuffer(ORIGIN).codePointBefore(2), 'A');
|
||||
assertEquals(new StringBuffer(ORIGIN).codePointBefore(3), '\uDC00');
|
||||
assertEquals(new StringBuffer(ORIGIN).codePointCount(0, 3), 3);
|
||||
assertEquals(new StringBuffer(ORIGIN).codePointCount(1, 3), 2);
|
||||
assertEquals(new StringBuffer(ORIGIN).delete(0, 1).delete(1, 3)
|
||||
.indexOf("A"), 0);
|
||||
assertEquals(
|
||||
new StringBuffer(ORIGIN).replace(0, 1, "B").replace(2, 4, "C")
|
||||
.indexOf("A"), 1);
|
||||
assertEquals(new StringBuffer(ORIGIN).substring(1, 4).substring(0, 1)
|
||||
.indexOf("A"), 0);
|
||||
assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(0, 1), 1);
|
||||
assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(1, 1), 2);
|
||||
assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(2, 1), 3);
|
||||
check(new StringBuffer(ORIGIN).reverse(), "\uFF21\uDC00A\uD801");
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests for "A\uDC01\uFF21\uD801"
|
||||
*/
|
||||
@Test
|
||||
public void testCompactStringForSupplementaryCodePointMixed4() {
|
||||
final String ORIGIN = "A\uDC01\uFF21\uD801";
|
||||
assertEquals(new StringBuffer(ORIGIN).codePointAt(1), '\uDC01');
|
||||
assertEquals(new StringBuffer(ORIGIN).codePointAt(3), '\uD801');
|
||||
assertEquals(new StringBuffer(ORIGIN).codePointBefore(1), 'A');
|
||||
assertEquals(new StringBuffer(ORIGIN).codePointBefore(2), '\uDC01');
|
||||
assertEquals(new StringBuffer(ORIGIN).codePointBefore(3), '\uFF21');
|
||||
assertEquals(new StringBuffer(ORIGIN).codePointCount(0, 3), 3);
|
||||
assertEquals(new StringBuffer(ORIGIN).codePointCount(1, 3), 2);
|
||||
assertEquals(new StringBuffer(ORIGIN).delete(1, 4).indexOf("A"), 0);
|
||||
assertEquals(new StringBuffer(ORIGIN).replace(1, 4, "B").indexOf("A"),
|
||||
0);
|
||||
assertEquals(new StringBuffer(ORIGIN).substring(0, 1).indexOf("A"), 0);
|
||||
assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(0, 1), 1);
|
||||
assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(1, 1), 2);
|
||||
assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(2, 1), 3);
|
||||
check(new StringBuffer(ORIGIN).reverse(), "\uD801\uFF21\uDC01A");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompactStringMisc() {
|
||||
String ascii = "abcdefgh";
|
||||
String asciiMixed = "abc" + "\u4e00\u4e01\u4e02" + "fgh";
|
||||
String bmp = "\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05\u4e06\u4e07\u4e08";
|
||||
String bmpMixed = "\u4e00\u4e01\u4e02" + "ABC" + "\u4e06\u4e07\u4e08";
|
||||
|
||||
check(new StringBuffer().append(ascii).delete(0, 20).toString(),
|
||||
"");
|
||||
check(new StringBuffer().append(ascii).delete(3, 20).toString(),
|
||||
"abc");
|
||||
check(new StringBuffer().append(ascii).delete(3, 6).toString(),
|
||||
"abcgh");
|
||||
check(new StringBuffer().append(ascii).deleteCharAt(0).toString(),
|
||||
"bcdefgh");
|
||||
check(new StringBuffer().append(ascii).deleteCharAt(3).toString(),
|
||||
"abcefgh");
|
||||
check(new StringBuffer().append(asciiMixed).delete(3, 6).toString(),
|
||||
"abcfgh");
|
||||
check(new StringBuffer().append(asciiMixed).deleteCharAt(3).toString(),
|
||||
"abc\u4e01\u4e02fgh");
|
||||
check(new StringBuffer().append(asciiMixed).deleteCharAt(3)
|
||||
.deleteCharAt(3)
|
||||
.deleteCharAt(3).toString(),
|
||||
"abcfgh");
|
||||
check(new StringBuffer().append(bmp).delete(0, 20).toString(),
|
||||
"");
|
||||
check(new StringBuffer().append(bmp).delete(3, 20).toString(),
|
||||
"\u4e00\u4e01\u4e02");
|
||||
check(new StringBuffer().append(bmp).delete(3, 6).toString(),
|
||||
"\u4e00\u4e01\u4e02\u4e06\u4e07\u4e08");
|
||||
check(new StringBuffer().append(bmp).deleteCharAt(0).toString(),
|
||||
"\u4e01\u4e02\u4e03\u4e04\u4e05\u4e06\u4e07\u4e08");
|
||||
check(new StringBuffer().append(bmp).deleteCharAt(3).toString(),
|
||||
"\u4e00\u4e01\u4e02\u4e04\u4e05\u4e06\u4e07\u4e08");
|
||||
check(new StringBuffer().append(bmpMixed).delete(3, 6).toString(),
|
||||
"\u4e00\u4e01\u4e02\u4e06\u4e07\u4e08");
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
check(new StringBuffer().append(ascii).replace(3, 6, "AB").toString(),
|
||||
"abcABgh");
|
||||
check(new StringBuffer().append(asciiMixed).replace(3, 6, "AB").toString(),
|
||||
"abcABfgh");
|
||||
check(new StringBuffer().append(bmp).replace(3, 6, "AB").toString(),
|
||||
"\u4e00\u4e01\u4e02AB\u4e06\u4e07\u4e08");
|
||||
|
||||
check(new StringBuffer().append(bmpMixed).replace(3, 6, "").toString(),
|
||||
"\u4e00\u4e01\u4e02\u4e06\u4e07\u4e08");
|
||||
|
||||
check(new StringBuffer().append(ascii).replace(3, 6, "\u4e01\u4e02").toString(),
|
||||
"abc\u4e01\u4e02gh");
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
check(new StringBuffer().append(ascii).insert(3, "").toString(),
|
||||
"abcdefgh");
|
||||
check(new StringBuffer().append(ascii).insert(3, "AB").toString(),
|
||||
"abcABdefgh");
|
||||
check(new StringBuffer().append(ascii).insert(3, "\u4e01\u4e02").toString(),
|
||||
"abc\u4e01\u4e02defgh");
|
||||
|
||||
check(new StringBuffer().append(asciiMixed).insert(0, 'A').toString(),
|
||||
"Aabc\u4e00\u4e01\u4e02fgh");
|
||||
check(new StringBuffer().append(asciiMixed).insert(3, "A").toString(),
|
||||
"abcA\u4e00\u4e01\u4e02fgh");
|
||||
|
||||
check(new StringBuffer().append(ascii).insert(3, 1234567).toString(),
|
||||
"abc1234567defgh");
|
||||
check(new StringBuffer().append(bmp).insert(3, 1234567).toString(),
|
||||
"\u4e00\u4e01\u4e021234567\u4e03\u4e04\u4e05\u4e06\u4e07\u4e08");
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
check(new StringBuffer().append(ascii).append(1.23456).toString(),
|
||||
"abcdefgh1.23456");
|
||||
check(new StringBuffer().append(bmp).append(1.23456).toString(),
|
||||
"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05\u4e06\u4e07\u4e081.23456");
|
||||
}
|
||||
|
||||
private void checkGetChars(StringBuffer sb, int srcBegin, int srcEnd,
|
||||
char expected[]) {
|
||||
char[] dst = new char[srcEnd - srcBegin];
|
||||
sb.getChars(srcBegin, srcEnd, dst, 0);
|
||||
assertTrue(Arrays.equals(dst, expected));
|
||||
}
|
||||
|
||||
private void checkSetCharAt(StringBuffer sb, int index, char ch,
|
||||
String expected) {
|
||||
sb.setCharAt(index, ch);
|
||||
check(sb, expected);
|
||||
}
|
||||
|
||||
private void checkSetLength(StringBuffer sb, int newLength, String expected) {
|
||||
sb.setLength(newLength);
|
||||
check(sb, expected);
|
||||
}
|
||||
|
||||
private void check(StringBuffer sb, String expected) {
|
||||
check(sb.toString(), expected);
|
||||
}
|
||||
|
||||
private void check(String str, String expected) {
|
||||
assertTrue(str.equals(expected), String.format(
|
||||
"Get (%s) but expect (%s), ", escapeNonASCIIs(str),
|
||||
escapeNonASCIIs(expected)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Because right now system default charset in JPRT environment is only
|
||||
* guaranteed to support ASCII characters in log, so we escape them.
|
||||
*/
|
||||
private String escapeNonASCIIs(String str) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < str.length(); i++) {
|
||||
char c = str.charAt(i);
|
||||
if (c > 0x7F) {
|
||||
sb.append("\\u").append(Integer.toHexString((int) c));
|
||||
} else {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static jdk.testlibrary.SerializationUtils.*;
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8077559
|
||||
* @library /lib/testlibrary
|
||||
* @build jdk.testlibrary.SerializationUtils
|
||||
* @summary Tests Compact String. This one is testing StringBuffer serialization
|
||||
* among -XX:+CompactStrings/-XX:-CompactStrings/LegacyStringBuffer
|
||||
* @run testng/othervm -XX:+CompactStrings CompactStringBufferSerialization
|
||||
* @run testng/othervm -XX:-CompactStrings CompactStringBufferSerialization
|
||||
*/
|
||||
|
||||
public class CompactStringBufferSerialization {
|
||||
@DataProvider
|
||||
public Object[][] provider() {
|
||||
return new Object[][] {
|
||||
// every byte array is serialized from corresponding StringBuilder object
|
||||
// by previous JDK(build 1.8.0_45-b14).
|
||||
new Object[] {
|
||||
new StringBuffer(""),
|
||||
new byte[] { -84, -19, 0, 5, 115, 114, 0, 22, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 102,
|
||||
102, 101, 114, 47, 7, 7, -39, -22, -56, -22, -45, 3, 0, 3, 73, 0, 5, 99, 111, 117, 110, 116, 90, 0, 6, 115, 104, 97, 114, 101,
|
||||
100, 91, 0, 5, 118, 97, 108, 117, 101, 116, 0, 2, 91, 67, 120, 112, 0, 0, 0, 0, 0, 117, 114, 0, 2, 91, 67, -80, 38, 102, -80,
|
||||
-30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 120 } },
|
||||
new Object[] {
|
||||
new StringBuffer("A"),
|
||||
new byte[] { -84, -19, 0, 5, 115, 114, 0, 22, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 102,
|
||||
102, 101, 114, 47, 7, 7, -39, -22, -56, -22, -45, 3, 0, 3, 73, 0, 5, 99, 111, 117, 110, 116, 90, 0, 6, 115, 104, 97, 114, 101,
|
||||
100, 91, 0, 5, 118, 97, 108, 117, 101, 116, 0, 2, 91, 67, 120, 112, 0, 0, 0, 1, 0, 117, 114, 0, 2, 91, 67, -80, 38, 102, -80,
|
||||
-30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 17, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } },
|
||||
new Object[] {
|
||||
new StringBuffer("AB"),
|
||||
new byte[] { -84, -19, 0, 5, 115, 114, 0, 22, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 102,
|
||||
102, 101, 114, 47, 7, 7, -39, -22, -56, -22, -45, 3, 0, 3, 73, 0, 5, 99, 111, 117, 110, 116, 90, 0, 6, 115, 104, 97, 114, 101,
|
||||
100, 91, 0, 5, 118, 97, 108, 117, 101, 116, 0, 2, 91, 67, 120, 112, 0, 0, 0, 2, 0, 117, 114, 0, 2, 91, 67, -80, 38, 102, -80,
|
||||
-30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 18, 0, 65, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } },
|
||||
new Object[] {
|
||||
new StringBuffer("abcdefghijk"),
|
||||
new byte[] { -84, -19, 0, 5, 115, 114, 0, 22, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 102,
|
||||
102, 101, 114, 47, 7, 7, -39, -22, -56, -22, -45, 3, 0, 3, 73, 0, 5, 99, 111, 117, 110, 116, 90, 0, 6, 115, 104, 97, 114, 101,
|
||||
100, 91, 0, 5, 118, 97, 108, 117, 101, 116, 0, 2, 91, 67, 120, 112, 0, 0, 0, 11, 0, 117, 114, 0, 2, 91, 67, -80, 38, 102, -80,
|
||||
-30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 27, 0, 97, 0, 98, 0, 99, 0, 100, 0, 101, 0, 102, 0, 103, 0, 104, 0, 105, 0,
|
||||
106, 0, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } },
|
||||
new Object[] {
|
||||
new StringBuffer("\uff21"),
|
||||
new byte[] { -84, -19, 0, 5, 115, 114, 0, 22, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 102,
|
||||
102, 101, 114, 47, 7, 7, -39, -22, -56, -22, -45, 3, 0, 3, 73, 0, 5, 99, 111, 117, 110, 116, 90, 0, 6, 115, 104, 97, 114, 101,
|
||||
100, 91, 0, 5, 118, 97, 108, 117, 101, 116, 0, 2, 91, 67, 120, 112, 0, 0, 0, 1, 0, 117, 114, 0, 2, 91, 67, -80, 38, 102, -80,
|
||||
-30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 17, -1, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } },
|
||||
new Object[] {
|
||||
new StringBuffer("\uff21\uff22"),
|
||||
new byte[] { -84, -19, 0, 5, 115, 114, 0, 22, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 102,
|
||||
102, 101, 114, 47, 7, 7, -39, -22, -56, -22, -45, 3, 0, 3, 73, 0, 5, 99, 111, 117, 110, 116, 90, 0, 6, 115, 104, 97, 114, 101,
|
||||
100, 91, 0, 5, 118, 97, 108, 117, 101, 116, 0, 2, 91, 67, 120, 112, 0, 0, 0, 2, 0, 117, 114, 0, 2, 91, 67, -80, 38, 102, -80,
|
||||
-30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 18, -1, 33, -1, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } },
|
||||
new Object[] {
|
||||
new StringBuffer("\uff21A\uff21A\uff21A\uff21A\uff21A"),
|
||||
new byte[] { -84, -19, 0, 5, 115, 114, 0, 22, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 102,
|
||||
102, 101, 114, 47, 7, 7, -39, -22, -56, -22, -45, 3, 0, 3, 73, 0, 5, 99, 111, 117, 110, 116, 90, 0, 6, 115, 104, 97, 114, 101,
|
||||
100, 91, 0, 5, 118, 97, 108, 117, 101, 116, 0, 2, 91, 67, 120, 112, 0, 0, 0, 10, 0, 117, 114, 0, 2, 91, 67, -80, 38, 102, -80,
|
||||
-30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 26, -1, 33, 0, 65, -1, 33, 0, 65, -1, 33, 0, 65, -1, 33, 0, 65, -1, 33, 0, 65,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } },
|
||||
new Object[] {
|
||||
new StringBuffer("A\uff21B\uff22C\uff23D\uff24E\uff25F\uff26G\uff27H\uff28"),
|
||||
new byte[] { -84, -19, 0, 5, 115, 114, 0, 22, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 102,
|
||||
102, 101, 114, 47, 7, 7, -39, -22, -56, -22, -45, 3, 0, 3, 73, 0, 5, 99, 111, 117, 110, 116, 90, 0, 6, 115, 104, 97, 114, 101,
|
||||
100, 91, 0, 5, 118, 97, 108, 117, 101, 116, 0, 2, 91, 67, 120, 112, 0, 0, 0, 16, 0, 117, 114, 0, 2, 91, 67, -80, 38, 102, -80,
|
||||
-30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 32, 0, 65, -1, 33, 0, 66, -1, 34, 0, 67, -1, 35, 0, 68, -1, 36, 0, 69, -1, 37,
|
||||
0, 70, -1, 38, 0, 71, -1, 39, 0, 72, -1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 120 } },
|
||||
new Object[] {
|
||||
new StringBuffer("\uff21A\uff22B\uff23C\uff24D\uff25E\uff26F\uff27G\uff28H"),
|
||||
new byte[] { -84, -19, 0, 5, 115, 114, 0, 22, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 102,
|
||||
102, 101, 114, 47, 7, 7, -39, -22, -56, -22, -45, 3, 0, 3, 73, 0, 5, 99, 111, 117, 110, 116, 90, 0, 6, 115, 104, 97, 114, 101,
|
||||
100, 91, 0, 5, 118, 97, 108, 117, 101, 116, 0, 2, 91, 67, 120, 112, 0, 0, 0, 16, 0, 117, 114, 0, 2, 91, 67, -80, 38, 102, -80,
|
||||
-30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 32, -1, 33, 0, 65, -1, 34, 0, 66, -1, 35, 0, 67, -1, 36, 0, 68, -1, 37, 0, 69,
|
||||
-1, 38, 0, 70, -1, 39, 0, 71, -1, 40, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 120 } },
|
||||
new Object[] {
|
||||
new StringBuffer("\ud801\udc00\ud801\udc01\uff21A"),
|
||||
new byte[] { -84, -19, 0, 5, 115, 114, 0, 22, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 102,
|
||||
102, 101, 114, 47, 7, 7, -39, -22, -56, -22, -45, 3, 0, 3, 73, 0, 5, 99, 111, 117, 110, 116, 90, 0, 6, 115, 104, 97, 114, 101,
|
||||
100, 91, 0, 5, 118, 97, 108, 117, 101, 116, 0, 2, 91, 67, 120, 112, 0, 0, 0, 6, 0, 117, 114, 0, 2, 91, 67, -80, 38, 102, -80,
|
||||
-30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 22, -40, 1, -36, 0, -40, 1, -36, 1, -1, 33, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } },
|
||||
new Object[] {
|
||||
new StringBuffer("\uff21\uff22\uff21\uff22\uff21\uff22\uff21\uff22\uff21\uff22"),
|
||||
new byte[] { -84, -19, 0, 5, 115, 114, 0, 22, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 102,
|
||||
102, 101, 114, 47, 7, 7, -39, -22, -56, -22, -45, 3, 0, 3, 73, 0, 5, 99, 111, 117, 110, 116, 90, 0, 6, 115, 104, 97, 114, 101,
|
||||
100, 91, 0, 5, 118, 97, 108, 117, 101, 116, 0, 2, 91, 67, 120, 112, 0, 0, 0, 10, 0, 117, 114, 0, 2, 91, 67, -80, 38, 102, -80,
|
||||
-30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 26, -1, 33, -1, 34, -1, 33, -1, 34, -1, 33, -1, 34, -1, 33, -1, 34, -1, 33, -1,
|
||||
34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } } };
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify serialization works between Compact StringBuffer/Legacy StringBuffer
|
||||
*/
|
||||
@Test(dataProvider = "provider")
|
||||
public void test(StringBuffer sbContent, byte[] baInJDK8) throws Exception {
|
||||
// Serialize a StringBuffer object into byte array.
|
||||
byte[] ba = serialize(sbContent);
|
||||
assertEquals(ba, baInJDK8);
|
||||
// Deserialize a StringBuffer object from byte array which is generated by previous JDK(build 1.8.0_45-b14).
|
||||
Object obj = deserialize(ba);
|
||||
assertEquals(obj.getClass(), StringBuffer.class);
|
||||
assertTrue(equals((StringBuffer)obj, sbContent));
|
||||
}
|
||||
|
||||
boolean equals(StringBuffer sb, StringBuffer expected) {
|
||||
if(sb.length() == expected.length()
|
||||
&& sb.capacity() == expected.capacity()
|
||||
&& sb.toString().equals(expected.toString())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -94,7 +94,7 @@ public class Exceptions {
|
||||
|
||||
System.out.println("StringBuffer.replace(int start, int end, String str)");
|
||||
tryCatch(" -1, 2, \" \"",
|
||||
new StringIndexOutOfBoundsException(-1),
|
||||
new StringIndexOutOfBoundsException("start -1, end 2, length 7"),
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
StringBuffer sb = new StringBuffer("hilbert");
|
||||
@ -102,14 +102,14 @@ public class Exceptions {
|
||||
}});
|
||||
|
||||
tryCatch(" 7, 8, \" \"",
|
||||
new StringIndexOutOfBoundsException("start > length()"),
|
||||
new StringIndexOutOfBoundsException("start 7, end 6, length 6"),
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
StringBuffer sb = new StringBuffer("banach");
|
||||
sb.replace(7, 8, " ");
|
||||
}});
|
||||
tryCatch(" 2, 1, \" \"",
|
||||
new StringIndexOutOfBoundsException("start > end"),
|
||||
new StringIndexOutOfBoundsException("start 2, end 1, length 7"),
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
StringBuffer sb = new StringBuffer("riemann");
|
||||
|
@ -264,4 +264,3 @@ public class BuilderForwarding {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
414
jdk/test/java/lang/StringBuilder/CompactStringBuilder.java
Normal file
414
jdk/test/java/lang/StringBuilder/CompactStringBuilder.java
Normal file
@ -0,0 +1,414 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8054307 8077559
|
||||
* @summary Tests Compact String. This test is testing StringBuilder
|
||||
* behavior related to Compact String.
|
||||
* @run testng/othervm -XX:+CompactStrings CompactStringBuilder
|
||||
* @run testng/othervm -XX:-CompactStrings CompactStringBuilder
|
||||
*/
|
||||
|
||||
public class CompactStringBuilder {
|
||||
|
||||
/*
|
||||
* Tests for "A"
|
||||
*/
|
||||
@Test
|
||||
public void testCompactStringBuilderForLatinA() {
|
||||
final String ORIGIN = "A";
|
||||
/*
|
||||
* Because right now ASCII is the default encoding parameter for source
|
||||
* code in JDK build environment, so we escape them. same as below.
|
||||
*/
|
||||
check(new StringBuilder(ORIGIN).append(new char[] { '\uFF21' }),
|
||||
"A\uFF21");
|
||||
check(new StringBuilder(ORIGIN).append(new StringBuffer("\uFF21")),
|
||||
"A\uFF21");
|
||||
check(new StringBuilder(ORIGIN).append("\uFF21"), "A\uFF21");
|
||||
check(new StringBuilder(ORIGIN).append(new StringBuffer("\uFF21")),
|
||||
"A\uFF21");
|
||||
check(new StringBuilder(ORIGIN).delete(0, 1), "");
|
||||
check(new StringBuilder(ORIGIN).delete(0, 0), "A");
|
||||
check(new StringBuilder(ORIGIN).deleteCharAt(0), "");
|
||||
assertEquals(new StringBuilder(ORIGIN).indexOf("A", 0), 0);
|
||||
assertEquals(new StringBuilder(ORIGIN).indexOf("\uFF21", 0), -1);
|
||||
assertEquals(new StringBuilder(ORIGIN).indexOf("", 0), 0);
|
||||
assertEquals(new StringBuilder(ORIGIN).insert(1, "\uD801\uDC00")
|
||||
.indexOf("A", 0), 0);
|
||||
assertEquals(new StringBuilder(ORIGIN).insert(0, "\uD801\uDC00")
|
||||
.indexOf("A", 0), 2);
|
||||
check(new StringBuilder(ORIGIN).insert(0, new char[] {}), "A");
|
||||
check(new StringBuilder(ORIGIN).insert(1, new char[] { '\uFF21' }),
|
||||
"A\uFF21");
|
||||
check(new StringBuilder(ORIGIN).insert(0, new char[] { '\uFF21' }),
|
||||
"\uFF21A");
|
||||
check(new StringBuilder(ORIGIN).insert(0, new StringBuffer("\uFF21")),
|
||||
"\uFF21A");
|
||||
check(new StringBuilder(ORIGIN).insert(1, new StringBuffer("\uFF21")),
|
||||
"A\uFF21");
|
||||
check(new StringBuilder(ORIGIN).insert(0, ""), "A");
|
||||
check(new StringBuilder(ORIGIN).insert(0, "\uFF21"), "\uFF21A");
|
||||
check(new StringBuilder(ORIGIN).insert(1, "\uFF21"), "A\uFF21");
|
||||
assertEquals(new StringBuilder(ORIGIN).lastIndexOf("A"), 0);
|
||||
assertEquals(new StringBuilder(ORIGIN).lastIndexOf("\uFF21"), -1);
|
||||
assertEquals(new StringBuilder(ORIGIN).lastIndexOf(""), 1);
|
||||
check(new StringBuilder(ORIGIN).replace(0, 0, "\uFF21"), "\uFF21A");
|
||||
check(new StringBuilder(ORIGIN).replace(0, 1, "\uFF21"), "\uFF21");
|
||||
checkSetCharAt(new StringBuilder(ORIGIN), 0, '\uFF21', "\uFF21");
|
||||
checkSetLength(new StringBuilder(ORIGIN), 0, "");
|
||||
checkSetLength(new StringBuilder(ORIGIN), 1, "A");
|
||||
check(new StringBuilder(ORIGIN).substring(0), "A");
|
||||
check(new StringBuilder(ORIGIN).substring(1), "");
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests for "\uFF21"
|
||||
*/
|
||||
@Test
|
||||
public void testCompactStringBuilderForNonLatinA() {
|
||||
final String ORIGIN = "\uFF21";
|
||||
check(new StringBuilder(ORIGIN).append(new char[] { 'A' }), "\uFF21A");
|
||||
check(new StringBuilder(ORIGIN).append(new StringBuffer("A")), "\uFF21A");
|
||||
check(new StringBuilder(ORIGIN).append("A"), "\uFF21A");
|
||||
check(new StringBuilder(ORIGIN).append(new StringBuffer("A")), "\uFF21A");
|
||||
check(new StringBuilder(ORIGIN).delete(0, 1), "");
|
||||
check(new StringBuilder(ORIGIN).delete(0, 0), "\uFF21");
|
||||
check(new StringBuilder(ORIGIN).deleteCharAt(0), "");
|
||||
assertEquals(new StringBuilder(ORIGIN).indexOf("A", 0), -1);
|
||||
assertEquals(new StringBuilder(ORIGIN).indexOf("\uFF21", 0), 0);
|
||||
assertEquals(new StringBuilder(ORIGIN).indexOf("", 0), 0);
|
||||
check(new StringBuilder(ORIGIN).insert(0, new char[] {}), "\uFF21");
|
||||
check(new StringBuilder(ORIGIN).insert(1, new char[] { 'A' }), "\uFF21A");
|
||||
check(new StringBuilder(ORIGIN).insert(0, new char[] { 'A' }), "A\uFF21");
|
||||
check(new StringBuilder(ORIGIN).insert(0, new StringBuffer("A")),
|
||||
"A\uFF21");
|
||||
check(new StringBuilder(ORIGIN).insert(1, new StringBuffer("A")),
|
||||
"\uFF21A");
|
||||
check(new StringBuilder(ORIGIN).insert(0, ""), "\uFF21");
|
||||
check(new StringBuilder(ORIGIN).insert(0, "A"), "A\uFF21");
|
||||
check(new StringBuilder(ORIGIN).insert(1, "A"), "\uFF21A");
|
||||
assertEquals(new StringBuilder(ORIGIN).lastIndexOf("A"), -1);
|
||||
assertEquals(new StringBuilder(ORIGIN).lastIndexOf("\uFF21"), 0);
|
||||
assertEquals(new StringBuilder(ORIGIN).lastIndexOf(""), 1);
|
||||
check(new StringBuilder(ORIGIN).replace(0, 0, "A"), "A\uFF21");
|
||||
check(new StringBuilder(ORIGIN).replace(0, 1, "A"), "A");
|
||||
checkSetCharAt(new StringBuilder(ORIGIN), 0, 'A', "A");
|
||||
checkSetLength(new StringBuilder(ORIGIN), 0, "");
|
||||
checkSetLength(new StringBuilder(ORIGIN), 1, "\uFF21");
|
||||
check(new StringBuilder(ORIGIN).substring(0), "\uFF21");
|
||||
check(new StringBuilder(ORIGIN).substring(1), "");
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests for "\uFF21A"
|
||||
*/
|
||||
@Test
|
||||
public void testCompactStringBuilderForMixedA1() {
|
||||
final String ORIGIN = "\uFF21A";
|
||||
check(new StringBuilder(ORIGIN).delete(0, 1), "A");
|
||||
check(new StringBuilder(ORIGIN).delete(1, 2), "\uFF21");
|
||||
check(new StringBuilder(ORIGIN).deleteCharAt(1), "\uFF21");
|
||||
check(new StringBuilder(ORIGIN).deleteCharAt(0), "A");
|
||||
assertEquals(new StringBuilder(ORIGIN).indexOf("A", 0), 1);
|
||||
assertEquals(new StringBuilder(ORIGIN).indexOf("\uFF21", 0), 0);
|
||||
assertEquals(new StringBuilder(ORIGIN).indexOf("", 0), 0);
|
||||
check(new StringBuilder(ORIGIN).insert(1, new char[] { 'A' }),
|
||||
"\uFF21AA");
|
||||
check(new StringBuilder(ORIGIN).insert(0, new char[] { '\uFF21' }),
|
||||
"\uFF21\uFF21A");
|
||||
assertEquals(new StringBuilder(ORIGIN).lastIndexOf("A"), 1);
|
||||
assertEquals(new StringBuilder(ORIGIN).lastIndexOf("\uFF21"), 0);
|
||||
assertEquals(new StringBuilder(ORIGIN).lastIndexOf(""), 2);
|
||||
check(new StringBuilder(ORIGIN).replace(0, 0, "A"), "A\uFF21A");
|
||||
check(new StringBuilder(ORIGIN).replace(0, 1, "A"), "AA");
|
||||
checkSetCharAt(new StringBuilder(ORIGIN), 0, 'A', "AA");
|
||||
checkSetLength(new StringBuilder(ORIGIN), 0, "");
|
||||
checkSetLength(new StringBuilder(ORIGIN), 1, "\uFF21");
|
||||
check(new StringBuilder(ORIGIN).substring(0), "\uFF21A");
|
||||
check(new StringBuilder(ORIGIN).substring(1), "A");
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests for "A\uFF21"
|
||||
*/
|
||||
@Test
|
||||
public void testCompactStringBuilderForMixedA2() {
|
||||
final String ORIGIN = "A\uFF21";
|
||||
check(new StringBuilder(ORIGIN).replace(1, 2, "A"), "AA");
|
||||
checkSetLength(new StringBuilder(ORIGIN), 1, "A");
|
||||
check(new StringBuilder(ORIGIN).substring(0), "A\uFF21");
|
||||
check(new StringBuilder(ORIGIN).substring(1), "\uFF21");
|
||||
check(new StringBuilder(ORIGIN).substring(0, 1), "A");
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests for "\uFF21A\uFF21A\uFF21A\uFF21A\uFF21A"
|
||||
*/
|
||||
@Test
|
||||
public void testCompactStringBuilderForDuplicatedMixedA1() {
|
||||
final String ORIGIN = "\uFF21A\uFF21A\uFF21A\uFF21A\uFF21A";
|
||||
checkSetLength(new StringBuilder(ORIGIN), 1, "\uFF21");
|
||||
assertEquals(new StringBuilder(ORIGIN).indexOf("A", 5), 5);
|
||||
assertEquals(new StringBuilder(ORIGIN).indexOf("\uFF21", 5), 6);
|
||||
assertEquals(new StringBuilder(ORIGIN).lastIndexOf("A"), 9);
|
||||
assertEquals(new StringBuilder(ORIGIN).lastIndexOf("\uFF21"), 8);
|
||||
assertEquals(new StringBuilder(ORIGIN).lastIndexOf(""), 10);
|
||||
check(new StringBuilder(ORIGIN).substring(9), "A");
|
||||
check(new StringBuilder(ORIGIN).substring(8), "\uFF21A");
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests for "A\uFF21A\uFF21A\uFF21A\uFF21A\uFF21"
|
||||
*/
|
||||
@Test
|
||||
public void testCompactStringBuilderForDuplicatedMixedA2() {
|
||||
final String ORIGIN = "A\uFF21A\uFF21A\uFF21A\uFF21A\uFF21";
|
||||
checkSetLength(new StringBuilder(ORIGIN), 1, "A");
|
||||
assertEquals(new StringBuilder(ORIGIN).indexOf("A", 5), 6);
|
||||
assertEquals(new StringBuilder(ORIGIN).indexOf("\uFF21", 5), 5);
|
||||
assertEquals(new StringBuilder(ORIGIN).lastIndexOf("A"), 8);
|
||||
assertEquals(new StringBuilder(ORIGIN).lastIndexOf("\uFF21"), 9);
|
||||
check(new StringBuilder(ORIGIN).substring(9), "\uFF21");
|
||||
check(new StringBuilder(ORIGIN).substring(8), "A\uFF21");
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests for "\uD801\uDC00\uD801\uDC01"
|
||||
*/
|
||||
@Test
|
||||
public void testCompactStringForSupplementaryCodePoint() {
|
||||
final String ORIGIN = "\uD801\uDC00\uD801\uDC01";
|
||||
check(new StringBuilder(ORIGIN).append("A"), "\uD801\uDC00\uD801\uDC01A");
|
||||
check(new StringBuilder(ORIGIN).append("\uFF21"),
|
||||
"\uD801\uDC00\uD801\uDC01\uFF21");
|
||||
check(new StringBuilder(ORIGIN).appendCodePoint('A'),
|
||||
"\uD801\uDC00\uD801\uDC01A");
|
||||
check(new StringBuilder(ORIGIN).appendCodePoint('\uFF21'),
|
||||
"\uD801\uDC00\uD801\uDC01\uFF21");
|
||||
assertEquals(new StringBuilder(ORIGIN).charAt(0), '\uD801');
|
||||
assertEquals(new StringBuilder(ORIGIN).codePointAt(0),
|
||||
Character.codePointAt(ORIGIN, 0));
|
||||
assertEquals(new StringBuilder(ORIGIN).codePointAt(1),
|
||||
Character.codePointAt(ORIGIN, 1));
|
||||
assertEquals(new StringBuilder(ORIGIN).codePointBefore(2),
|
||||
Character.codePointAt(ORIGIN, 0));
|
||||
assertEquals(new StringBuilder(ORIGIN).codePointCount(1, 3), 2);
|
||||
check(new StringBuilder(ORIGIN).delete(0, 2), "\uD801\uDC01");
|
||||
check(new StringBuilder(ORIGIN).delete(0, 3), "\uDC01");
|
||||
check(new StringBuilder(ORIGIN).deleteCharAt(1), "\uD801\uD801\uDC01");
|
||||
checkGetChars(new StringBuilder(ORIGIN), 0, 3, new char[] { '\uD801',
|
||||
'\uDC00', '\uD801' });
|
||||
assertEquals(new StringBuilder(ORIGIN).indexOf("\uD801\uDC01"), 2);
|
||||
assertEquals(new StringBuilder(ORIGIN).indexOf("\uDC01"), 3);
|
||||
assertEquals(new StringBuilder(ORIGIN).indexOf("\uFF21"), -1);
|
||||
assertEquals(new StringBuilder(ORIGIN).indexOf("A"), -1);
|
||||
check(new StringBuilder(ORIGIN).insert(0, "\uFF21"),
|
||||
"\uFF21\uD801\uDC00\uD801\uDC01");
|
||||
check(new StringBuilder(ORIGIN).insert(1, "\uFF21"),
|
||||
"\uD801\uFF21\uDC00\uD801\uDC01");
|
||||
check(new StringBuilder(ORIGIN).insert(1, "A"),
|
||||
"\uD801A\uDC00\uD801\uDC01");
|
||||
assertEquals(new StringBuilder(ORIGIN).lastIndexOf("\uDC00\uD801"), 1);
|
||||
assertEquals(new StringBuilder(ORIGIN).lastIndexOf("\uD801"), 2);
|
||||
assertEquals(new StringBuilder(ORIGIN).lastIndexOf("\uFF21"), -1);
|
||||
assertEquals(new StringBuilder(ORIGIN).lastIndexOf("A"), -1);
|
||||
assertEquals(new StringBuilder(ORIGIN).length(), 4);
|
||||
assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(1, 1), 2);
|
||||
assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(0, 1), 2);
|
||||
check(new StringBuilder(ORIGIN).replace(0, 2, "A"), "A\uD801\uDC01");
|
||||
check(new StringBuilder(ORIGIN).replace(0, 3, "A"), "A\uDC01");
|
||||
check(new StringBuilder(ORIGIN).replace(0, 2, "\uFF21"),
|
||||
"\uFF21\uD801\uDC01");
|
||||
check(new StringBuilder(ORIGIN).replace(0, 3, "\uFF21"), "\uFF21\uDC01");
|
||||
check(new StringBuilder(ORIGIN).reverse(), "\uD801\uDC01\uD801\uDC00");
|
||||
checkSetCharAt(new StringBuilder(ORIGIN), 1, '\uDC01',
|
||||
"\uD801\uDC01\uD801\uDC01");
|
||||
checkSetCharAt(new StringBuilder(ORIGIN), 1, 'A', "\uD801A\uD801\uDC01");
|
||||
checkSetLength(new StringBuilder(ORIGIN), 2, "\uD801\uDC00");
|
||||
checkSetLength(new StringBuilder(ORIGIN), 3, "\uD801\uDC00\uD801");
|
||||
check(new StringBuilder(ORIGIN).substring(1, 3), "\uDC00\uD801");
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests for "A\uD801\uDC00\uFF21"
|
||||
*/
|
||||
@Test
|
||||
public void testCompactStringForSupplementaryCodePointMixed1() {
|
||||
final String ORIGIN = "A\uD801\uDC00\uFF21";
|
||||
assertEquals(new StringBuilder(ORIGIN).codePointBefore(3),
|
||||
Character.codePointAt(ORIGIN, 1));
|
||||
assertEquals(new StringBuilder(ORIGIN).codePointBefore(2), '\uD801');
|
||||
assertEquals(new StringBuilder(ORIGIN).codePointBefore(1), 'A');
|
||||
assertEquals(new StringBuilder(ORIGIN).codePointCount(0, 3), 2);
|
||||
assertEquals(new StringBuilder(ORIGIN).codePointCount(0, 4), 3);
|
||||
check(new StringBuilder(ORIGIN).delete(0, 1), "\uD801\uDC00\uFF21");
|
||||
check(new StringBuilder(ORIGIN).delete(0, 1).delete(2, 3),
|
||||
"\uD801\uDC00");
|
||||
check(new StringBuilder(ORIGIN).deleteCharAt(3).deleteCharAt(0),
|
||||
"\uD801\uDC00");
|
||||
assertEquals(new StringBuilder(ORIGIN).indexOf("\uFF21"), 3);
|
||||
assertEquals(new StringBuilder(ORIGIN).indexOf("A"), 0);
|
||||
assertEquals(new StringBuilder(ORIGIN).lastIndexOf("\uFF21"), 3);
|
||||
assertEquals(new StringBuilder(ORIGIN).lastIndexOf("A"), 0);
|
||||
assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(0, 1), 1);
|
||||
assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(1, 1), 3);
|
||||
check(new StringBuilder(ORIGIN).replace(1, 3, "A"), "AA\uFF21");
|
||||
check(new StringBuilder(ORIGIN).replace(1, 4, "A"), "AA");
|
||||
check(new StringBuilder(ORIGIN).replace(1, 4, ""), "A");
|
||||
check(new StringBuilder(ORIGIN).reverse(), "\uFF21\uD801\uDC00A");
|
||||
checkSetLength(new StringBuilder(ORIGIN), 1, "A");
|
||||
check(new StringBuilder(ORIGIN).substring(0, 1), "A");
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests for "\uD801\uDC00\uFF21A"
|
||||
*/
|
||||
@Test
|
||||
public void testCompactStringForSupplementaryCodePointMixed2() {
|
||||
final String ORIGIN = "\uD801\uDC00\uFF21A";
|
||||
assertEquals(new StringBuilder(ORIGIN).codePointBefore(3),
|
||||
Character.codePointAt(ORIGIN, 2));
|
||||
assertEquals(new StringBuilder(ORIGIN).codePointBefore(2),
|
||||
Character.codePointAt(ORIGIN, 0));
|
||||
assertEquals(new StringBuilder(ORIGIN).codePointBefore(1), '\uD801');
|
||||
assertEquals(new StringBuilder(ORIGIN).codePointCount(0, 3), 2);
|
||||
assertEquals(new StringBuilder(ORIGIN).codePointCount(0, 4), 3);
|
||||
check(new StringBuilder(ORIGIN).delete(0, 2), "\uFF21A");
|
||||
check(new StringBuilder(ORIGIN).delete(0, 3), "A");
|
||||
check(new StringBuilder(ORIGIN).deleteCharAt(0).deleteCharAt(0)
|
||||
.deleteCharAt(0), "A");
|
||||
assertEquals(new StringBuilder(ORIGIN).indexOf("A"), 3);
|
||||
assertEquals(new StringBuilder(ORIGIN).delete(0, 3).indexOf("A"), 0);
|
||||
assertEquals(new StringBuilder(ORIGIN).replace(0, 3, "B").indexOf("A"),
|
||||
1);
|
||||
assertEquals(new StringBuilder(ORIGIN).substring(3, 4).indexOf("A"), 0);
|
||||
assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(1, 1), 2);
|
||||
assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(0, 1), 2);
|
||||
assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(2, 1), 3);
|
||||
check(new StringBuilder(ORIGIN).replace(0, 3, "B"), "BA");
|
||||
check(new StringBuilder(ORIGIN).reverse(), "A\uFF21\uD801\uDC00");
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests for "\uD801A\uDC00\uFF21"
|
||||
*/
|
||||
@Test
|
||||
public void testCompactStringForSupplementaryCodePointMixed3() {
|
||||
final String ORIGIN = "\uD801A\uDC00\uFF21";
|
||||
assertEquals(new StringBuilder(ORIGIN).codePointAt(1), 'A');
|
||||
assertEquals(new StringBuilder(ORIGIN).codePointAt(3), '\uFF21');
|
||||
assertEquals(new StringBuilder(ORIGIN).codePointBefore(1), '\uD801');
|
||||
assertEquals(new StringBuilder(ORIGIN).codePointBefore(2), 'A');
|
||||
assertEquals(new StringBuilder(ORIGIN).codePointBefore(3), '\uDC00');
|
||||
assertEquals(new StringBuilder(ORIGIN).codePointCount(0, 3), 3);
|
||||
assertEquals(new StringBuilder(ORIGIN).codePointCount(1, 3), 2);
|
||||
assertEquals(new StringBuilder(ORIGIN).delete(0, 1).delete(1, 3)
|
||||
.indexOf("A"), 0);
|
||||
assertEquals(
|
||||
new StringBuilder(ORIGIN).replace(0, 1, "B").replace(2, 4, "C")
|
||||
.indexOf("A"), 1);
|
||||
assertEquals(new StringBuilder(ORIGIN).substring(1, 4).substring(0, 1)
|
||||
.indexOf("A"), 0);
|
||||
assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(0, 1), 1);
|
||||
assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(1, 1), 2);
|
||||
assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(2, 1), 3);
|
||||
check(new StringBuilder(ORIGIN).reverse(), "\uFF21\uDC00A\uD801");
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests for "A\uDC01\uFF21\uD801"
|
||||
*/
|
||||
@Test
|
||||
public void testCompactStringForSupplementaryCodePointMixed4() {
|
||||
final String ORIGIN = "A\uDC01\uFF21\uD801";
|
||||
assertEquals(new StringBuilder(ORIGIN).codePointAt(1), '\uDC01');
|
||||
assertEquals(new StringBuilder(ORIGIN).codePointAt(3), '\uD801');
|
||||
assertEquals(new StringBuilder(ORIGIN).codePointBefore(1), 'A');
|
||||
assertEquals(new StringBuilder(ORIGIN).codePointBefore(2), '\uDC01');
|
||||
assertEquals(new StringBuilder(ORIGIN).codePointBefore(3), '\uFF21');
|
||||
assertEquals(new StringBuilder(ORIGIN).codePointCount(0, 3), 3);
|
||||
assertEquals(new StringBuilder(ORIGIN).codePointCount(1, 3), 2);
|
||||
assertEquals(new StringBuilder(ORIGIN).delete(1, 4).indexOf("A"), 0);
|
||||
assertEquals(new StringBuilder(ORIGIN).replace(1, 4, "B").indexOf("A"),
|
||||
0);
|
||||
assertEquals(new StringBuilder(ORIGIN).substring(0, 1).indexOf("A"), 0);
|
||||
assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(0, 1), 1);
|
||||
assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(1, 1), 2);
|
||||
assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(2, 1), 3);
|
||||
check(new StringBuilder(ORIGIN).reverse(), "\uD801\uFF21\uDC01A");
|
||||
}
|
||||
|
||||
private void checkGetChars(StringBuilder sb, int srcBegin, int srcEnd,
|
||||
char expected[]) {
|
||||
char[] dst = new char[srcEnd - srcBegin];
|
||||
sb.getChars(srcBegin, srcEnd, dst, 0);
|
||||
assertTrue(Arrays.equals(dst, expected));
|
||||
}
|
||||
|
||||
private void checkSetCharAt(StringBuilder sb, int index, char ch,
|
||||
String expected) {
|
||||
sb.setCharAt(index, ch);
|
||||
check(sb, expected);
|
||||
}
|
||||
|
||||
private void checkSetLength(StringBuilder sb, int newLength, String expected) {
|
||||
sb.setLength(newLength);
|
||||
check(sb, expected);
|
||||
}
|
||||
|
||||
private void check(StringBuilder sb, String expected) {
|
||||
check(sb.toString(), expected);
|
||||
}
|
||||
|
||||
private void check(String str, String expected) {
|
||||
assertTrue(str.equals(expected), String.format(
|
||||
"Get (%s) but expect (%s), ", escapeNonASCIIs(str),
|
||||
escapeNonASCIIs(expected)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Because right now system default charset in JPRT environment is only
|
||||
* guaranteed to support ASCII characters in log, so we escape them.
|
||||
*/
|
||||
private String escapeNonASCIIs(String str) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < str.length(); i++) {
|
||||
char c = str.charAt(i);
|
||||
if (c > 0x7F) {
|
||||
sb.append("\\u").append(Integer.toHexString((int) c));
|
||||
} else {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static jdk.testlibrary.SerializationUtils.*;
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8077559
|
||||
* @library /lib/testlibrary
|
||||
* @build jdk.testlibrary.SerializationUtils
|
||||
* @summary Tests Compact String. This one is testing StringBuilder serialization
|
||||
* among -XX:+CompactStrings/-XX:-CompactStrings/LegacyStringBuilder
|
||||
* @run testng/othervm -XX:+CompactStrings CompactStringBuilderSerialization
|
||||
* @run testng/othervm -XX:-CompactStrings CompactStringBuilderSerialization
|
||||
*/
|
||||
|
||||
public class CompactStringBuilderSerialization {
|
||||
@DataProvider
|
||||
public Object[][] provider() {
|
||||
return new Object[][] {
|
||||
// every byte array is serialized from corresponding StringBuffer object
|
||||
// by previous JDK(build 1.8.0_45-b14).
|
||||
new Object[] {
|
||||
new StringBuilder(""),
|
||||
new byte[] { -84, -19, 0, 5, 115, 114, 0, 23, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 105,
|
||||
108, 100, 101, 114, 60, -43, -5, 20, 90, 76, 106, -53, 3, 0, 0, 120, 112, 119, 4, 0, 0, 0, 0, 117, 114, 0, 2, 91, 67, -80, 38,
|
||||
102, -80, -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } },
|
||||
new Object[] {
|
||||
new StringBuilder("A"),
|
||||
new byte[] { -84, -19, 0, 5, 115, 114, 0, 23, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 105,
|
||||
108, 100, 101, 114, 60, -43, -5, 20, 90, 76, 106, -53, 3, 0, 0, 120, 112, 119, 4, 0, 0, 0, 1, 117, 114, 0, 2, 91, 67, -80, 38,
|
||||
102, -80, -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 17, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } },
|
||||
new Object[] {
|
||||
new StringBuilder("AB"),
|
||||
new byte[] { -84, -19, 0, 5, 115, 114, 0, 23, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 105,
|
||||
108, 100, 101, 114, 60, -43, -5, 20, 90, 76, 106, -53, 3, 0, 0, 120, 112, 119, 4, 0, 0, 0, 2, 117, 114, 0, 2, 91, 67, -80, 38,
|
||||
102, -80, -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 18, 0, 65, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } },
|
||||
new Object[] {
|
||||
new StringBuilder("abcdefghijk"),
|
||||
new byte[] { -84, -19, 0, 5, 115, 114, 0, 23, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 105,
|
||||
108, 100, 101, 114, 60, -43, -5, 20, 90, 76, 106, -53, 3, 0, 0, 120, 112, 119, 4, 0, 0, 0, 11, 117, 114, 0, 2, 91, 67, -80, 38,
|
||||
102, -80, -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 27, 0, 97, 0, 98, 0, 99, 0, 100, 0, 101, 0, 102, 0, 103, 0, 104, 0,
|
||||
105, 0, 106, 0, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } },
|
||||
new Object[] {
|
||||
new StringBuilder("\uff21"),
|
||||
new byte[] { -84, -19, 0, 5, 115, 114, 0, 23, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 105,
|
||||
108, 100, 101, 114, 60, -43, -5, 20, 90, 76, 106, -53, 3, 0, 0, 120, 112, 119, 4, 0, 0, 0, 1, 117, 114, 0, 2, 91, 67, -80, 38,
|
||||
102, -80, -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 17, -1, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } },
|
||||
new Object[] {
|
||||
new StringBuilder("\uff21\uff22"),
|
||||
new byte[] { -84, -19, 0, 5, 115, 114, 0, 23, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 105,
|
||||
108, 100, 101, 114, 60, -43, -5, 20, 90, 76, 106, -53, 3, 0, 0, 120, 112, 119, 4, 0, 0, 0, 2, 117, 114, 0, 2, 91, 67, -80, 38,
|
||||
102, -80, -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 18, -1, 33, -1, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } },
|
||||
new Object[] {
|
||||
new StringBuilder("\uff21A\uff21A\uff21A\uff21A\uff21A"),
|
||||
new byte[] { -84, -19, 0, 5, 115, 114, 0, 23, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 105,
|
||||
108, 100, 101, 114, 60, -43, -5, 20, 90, 76, 106, -53, 3, 0, 0, 120, 112, 119, 4, 0, 0, 0, 10, 117, 114, 0, 2, 91, 67, -80, 38,
|
||||
102, -80, -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 26, -1, 33, 0, 65, -1, 33, 0, 65, -1, 33, 0, 65, -1, 33, 0, 65, -1,
|
||||
33, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } },
|
||||
new Object[] {
|
||||
new StringBuilder("A\uff21B\uff22C\uff23D\uff24E\uff25F\uff26G\uff27H\uff28"),
|
||||
new byte[] { -84, -19, 0, 5, 115, 114, 0, 23, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 105,
|
||||
108, 100, 101, 114, 60, -43, -5, 20, 90, 76, 106, -53, 3, 0, 0, 120, 112, 119, 4, 0, 0, 0, 16, 117, 114, 0, 2, 91, 67, -80, 38,
|
||||
102, -80, -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 32, 0, 65, -1, 33, 0, 66, -1, 34, 0, 67, -1, 35, 0, 68, -1, 36, 0,
|
||||
69, -1, 37, 0, 70, -1, 38, 0, 71, -1, 39, 0, 72, -1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } },
|
||||
new Object[] {
|
||||
new StringBuilder("\uff21A\uff22B\uff23C\uff24D\uff25E\uff26F\uff27G\uff28H"),
|
||||
new byte[] { -84, -19, 0, 5, 115, 114, 0, 23, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 105,
|
||||
108, 100, 101, 114, 60, -43, -5, 20, 90, 76, 106, -53, 3, 0, 0, 120, 112, 119, 4, 0, 0, 0, 16, 117, 114, 0, 2, 91, 67, -80, 38,
|
||||
102, -80, -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 32, -1, 33, 0, 65, -1, 34, 0, 66, -1, 35, 0, 67, -1, 36, 0, 68, -1,
|
||||
37, 0, 69, -1, 38, 0, 70, -1, 39, 0, 71, -1, 40, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 120 } },
|
||||
new Object[] {
|
||||
new StringBuilder("\ud801\udc00\ud801\udc01\uff21A"),
|
||||
new byte[] { -84, -19, 0, 5, 115, 114, 0, 23, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 105,
|
||||
108, 100, 101, 114, 60, -43, -5, 20, 90, 76, 106, -53, 3, 0, 0, 120, 112, 119, 4, 0, 0, 0, 6, 117, 114, 0, 2, 91, 67, -80, 38,
|
||||
102, -80, -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 22, -40, 1, -36, 0, -40, 1, -36, 1, -1, 33, 0, 65, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } },
|
||||
new Object[] {
|
||||
new StringBuilder("\uff21\uff22\uff21\uff22\uff21\uff22\uff21\uff22\uff21\uff22"),
|
||||
new byte[] { -84, -19, 0, 5, 115, 114, 0, 23, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 105,
|
||||
108, 100, 101, 114, 60, -43, -5, 20, 90, 76, 106, -53, 3, 0, 0, 120, 112, 119, 4, 0, 0, 0, 10, 117, 114, 0, 2, 91, 67, -80, 38,
|
||||
102, -80, -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 26, -1, 33, -1, 34, -1, 33, -1, 34, -1, 33, -1, 34, -1, 33, -1, 34,
|
||||
-1, 33, -1, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } } };
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify serialization works between Compact StringBuilder/Legacy StringBuilder
|
||||
*/
|
||||
@Test(dataProvider = "provider")
|
||||
public void test(StringBuilder sbContent, byte[] baInJDK8) throws Exception {
|
||||
// Serialize a StringBuilder object into byte array.
|
||||
byte[] ba = serialize(sbContent);
|
||||
assertEquals(ba, baInJDK8);
|
||||
// Deserialize a StringBuilder object from byte array which is generated by previous JDK(build 1.8.0_45-b14).
|
||||
Object obj = deserialize(ba);
|
||||
assertEquals(obj.getClass(), StringBuilder.class);
|
||||
assertTrue(equals((StringBuilder)obj, sbContent));
|
||||
}
|
||||
|
||||
boolean equals(StringBuilder sb, StringBuilder expected) {
|
||||
if(sb.length() == expected.length()
|
||||
&& sb.capacity() == expected.capacity()
|
||||
&& sb.toString().equals(expected.toString())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -94,21 +94,21 @@ public class Exceptions {
|
||||
|
||||
System.out.println("StringBuilder.replace(int start, int end, String str)");
|
||||
tryCatch(" -1, 2, \" \"",
|
||||
new StringIndexOutOfBoundsException(-1),
|
||||
new StringIndexOutOfBoundsException("start -1, end 2, length 7"),
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
StringBuilder sb = new StringBuilder("hilbert");
|
||||
sb.replace(-1, 2, " ");
|
||||
}});
|
||||
tryCatch(" 7, 8, \" \"",
|
||||
new StringIndexOutOfBoundsException("start > length()"),
|
||||
new StringIndexOutOfBoundsException("start 7, end 6, length 6"),
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
StringBuilder sb = new StringBuilder("banach");
|
||||
sb.replace(7, 8, " ");
|
||||
}});
|
||||
tryCatch(" 2, 1, \" \"",
|
||||
new StringIndexOutOfBoundsException("start > end"),
|
||||
new StringIndexOutOfBoundsException("start 2, end 1, length 7"),
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
StringBuilder sb = new StringBuilder("riemann");
|
||||
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package jdk.testlibrary;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* Common library for various test serialization utility functions.
|
||||
*/
|
||||
public final class SerializationUtils {
|
||||
/*
|
||||
* Serialize an object into byte array.
|
||||
*/
|
||||
public static byte[] serialize(Object obj) throws Exception {
|
||||
try (ByteArrayOutputStream bs = new ByteArrayOutputStream();
|
||||
ObjectOutputStream out = new ObjectOutputStream(bs);) {
|
||||
out.writeObject(obj);
|
||||
return bs.toByteArray();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Deserialize an object from byte array.
|
||||
*/
|
||||
public static Object deserialize(byte[] ba) throws Exception {
|
||||
try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(ba));) {
|
||||
return in.readObject();
|
||||
}
|
||||
}
|
||||
}
|
@ -22,7 +22,7 @@
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 6636323 6636319 7040220 7096080 7183053 8080248
|
||||
* @bug 6636323 6636319 7040220 7096080 7183053 8080248 8054307
|
||||
* @summary Test if StringCoding and NIO result have the same de/encoding result
|
||||
* @modules java.base/sun.nio.cs
|
||||
* @run main/othervm/timeout=2000 TestStringCoding
|
||||
@ -36,41 +36,61 @@ import java.nio.charset.*;
|
||||
public class TestStringCoding {
|
||||
public static void main(String[] args) throws Throwable {
|
||||
|
||||
// full bmp first
|
||||
char[] bmp = new char[0x10000];
|
||||
for (int i = 0; i < 0x10000; i++) {
|
||||
bmp[i] = (char)i;
|
||||
}
|
||||
char[] latin = Arrays.copyOf(bmp, 0x100);
|
||||
char[] ascii = Arrays.copyOf(bmp, 0x80);
|
||||
|
||||
byte[] latinBA = new byte[0x100];
|
||||
for (int i = 0; i < 0x100; i++) {
|
||||
latinBA[i] = (byte)i;
|
||||
}
|
||||
byte[] asciiBA = Arrays.copyOf(latinBA, 0x80);
|
||||
|
||||
for (Boolean hasSM: new boolean[] { false, true }) {
|
||||
if (hasSM)
|
||||
if (hasSM) {
|
||||
System.setSecurityManager(new PermissiveSecurityManger());
|
||||
}
|
||||
for (Charset cs: Charset.availableCharsets().values()) {
|
||||
if ("ISO-2022-CN".equals(cs.name()) ||
|
||||
"x-COMPOUND_TEXT".equals(cs.name()) ||
|
||||
"x-JISAutoDetect".equals(cs.name()))
|
||||
continue;
|
||||
System.out.printf("Testing(sm=%b) " + cs.name() + "....", hasSM);
|
||||
// full bmp first
|
||||
char[] bmpCA = new char[0x10000];
|
||||
for (int i = 0; i < 0x10000; i++) {
|
||||
bmpCA[i] = (char)i;
|
||||
}
|
||||
byte[] sbBA = new byte[0x100];
|
||||
for (int i = 0; i < 0x100; i++) {
|
||||
sbBA[i] = (byte)i;
|
||||
}
|
||||
test(cs, bmpCA, sbBA);
|
||||
|
||||
testNewString(cs, testGetBytes(cs, new String(bmp)));
|
||||
testNewString(cs, testGetBytes(cs, new String(latin)));
|
||||
testNewString(cs, testGetBytes(cs, new String(ascii)));
|
||||
testGetBytes(cs, testNewString(cs, latinBA));
|
||||
testGetBytes(cs, testNewString(cs, asciiBA));
|
||||
|
||||
// "randomed" sizes
|
||||
Random rnd = new Random();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
int clen = rnd.nextInt(0x10000);
|
||||
int blen = rnd.nextInt(0x100);
|
||||
//System.out.printf(" blen=%d, clen=%d%n", blen, clen);
|
||||
test(cs, Arrays.copyOf(bmpCA, clen), Arrays.copyOf(sbBA, blen));
|
||||
char[] bmp0 = Arrays.copyOf(bmp, rnd.nextInt(0x10000));
|
||||
testNewString(cs, testGetBytes(cs, new String(bmp0)));
|
||||
//add a pair of surrogates
|
||||
int pos = clen / 2;
|
||||
if ((pos + 1) < blen) {
|
||||
bmpCA[pos] = '\uD800';
|
||||
bmpCA[pos+1] = '\uDC00';
|
||||
int pos = bmp0.length / 2;
|
||||
if ((pos + 1) < bmp0.length) {
|
||||
bmp0[pos] = '\uD800';
|
||||
bmp0[pos+1] = '\uDC00';
|
||||
}
|
||||
test(cs, Arrays.copyOf(bmpCA, clen), Arrays.copyOf(sbBA, blen));
|
||||
}
|
||||
testNewString(cs, testGetBytes(cs, new String(bmp0)));
|
||||
|
||||
char[] latin0 = Arrays.copyOf(latin, rnd.nextInt(0x100));
|
||||
char[] ascii0 = Arrays.copyOf(ascii, rnd.nextInt(0x80));
|
||||
byte[] latinBA0 = Arrays.copyOf(latinBA, rnd.nextInt(0x100));
|
||||
byte[] asciiBA0 = Arrays.copyOf(asciiBA, rnd.nextInt(0x80));
|
||||
testNewString(cs, testGetBytes(cs, new String(latin0)));
|
||||
testNewString(cs, testGetBytes(cs, new String(ascii0)));
|
||||
testGetBytes(cs, testNewString(cs, latinBA0));
|
||||
testGetBytes(cs, testNewString(cs, asciiBA0));
|
||||
}
|
||||
testSurrogates(cs);
|
||||
testMixed(cs);
|
||||
System.out.println("done!");
|
||||
}
|
||||
@ -109,8 +129,9 @@ public class TestStringCoding {
|
||||
|
||||
//getBytes(cs);
|
||||
bmpBA = bmpStr.getBytes(cs);
|
||||
if (!Arrays.equals(bmpBA, baNIO))
|
||||
if (!Arrays.equals(bmpBA, baNIO)) {
|
||||
throw new RuntimeException("getBytes(cs) failed -> " + cs.name());
|
||||
}
|
||||
|
||||
//new String(csn);
|
||||
String strSC = new String(bmpBA, cs.name());
|
||||
@ -118,49 +139,61 @@ public class TestStringCoding {
|
||||
if(!strNIO.equals(strSC)) {
|
||||
throw new RuntimeException("new String(csn) failed -> " + cs.name());
|
||||
}
|
||||
|
||||
//new String(cs);
|
||||
strSC = new String(bmpBA, cs);
|
||||
if (!strNIO.equals(strSC))
|
||||
if (!strNIO.equals(strSC)) {
|
||||
throw new RuntimeException("new String(cs) failed -> " + cs.name());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void test(Charset cs, char[] bmpCA, byte[] sbBA) throws Throwable {
|
||||
String bmpStr = new String(bmpCA);
|
||||
CharsetDecoder dec = cs.newDecoder()
|
||||
.onMalformedInput(CodingErrorAction.REPLACE)
|
||||
.onUnmappableCharacter(CodingErrorAction.REPLACE);
|
||||
static byte[] getBytes(CharsetEncoder enc, String str) throws Throwable {
|
||||
ByteBuffer bf = enc.reset().encode(CharBuffer.wrap(str.toCharArray()));
|
||||
byte[] ba = new byte[bf.limit()];
|
||||
bf.get(ba, 0, ba.length);
|
||||
return ba;
|
||||
}
|
||||
|
||||
static byte[] testGetBytes(Charset cs, String str) throws Throwable {
|
||||
CharsetEncoder enc = cs.newEncoder()
|
||||
.onMalformedInput(CodingErrorAction.REPLACE)
|
||||
.onUnmappableCharacter(CodingErrorAction.REPLACE);
|
||||
|
||||
//getBytes(csn);
|
||||
byte[] baSC = bmpStr.getBytes(cs.name());
|
||||
ByteBuffer bf = enc.reset().encode(CharBuffer.wrap(bmpCA));
|
||||
byte[] baNIO = new byte[bf.limit()];
|
||||
bf.get(baNIO, 0, baNIO.length);
|
||||
if (!Arrays.equals(baSC, baNIO))
|
||||
byte[] baSC = str.getBytes(cs.name());
|
||||
byte[] baNIO = getBytes(enc, str);
|
||||
if (!Arrays.equals(baSC, baNIO)) {
|
||||
throw new RuntimeException("getBytes(csn) failed -> " + cs.name());
|
||||
|
||||
}
|
||||
//getBytes(cs);
|
||||
baSC = bmpStr.getBytes(cs);
|
||||
if (!Arrays.equals(baSC, baNIO))
|
||||
baSC = str.getBytes(cs);
|
||||
if (!Arrays.equals(baSC, baNIO)) {
|
||||
throw new RuntimeException("getBytes(cs) failed -> " + cs.name());
|
||||
}
|
||||
return baSC;
|
||||
}
|
||||
|
||||
static String testNewString(Charset cs, byte[] ba) throws Throwable {
|
||||
CharsetDecoder dec = cs.newDecoder()
|
||||
.onMalformedInput(CodingErrorAction.REPLACE)
|
||||
.onUnmappableCharacter(CodingErrorAction.REPLACE);
|
||||
//new String(csn);
|
||||
String strSC = new String(sbBA, cs.name());
|
||||
String strNIO = dec.reset().decode(ByteBuffer.wrap(sbBA)).toString();
|
||||
|
||||
if(!strNIO.equals(strSC))
|
||||
String strSC = new String(ba, cs.name());
|
||||
String strNIO = dec.reset().decode(ByteBuffer.wrap(ba)).toString();
|
||||
if(!strNIO.equals(strSC)) {
|
||||
throw new RuntimeException("new String(csn) failed -> " + cs.name());
|
||||
|
||||
}
|
||||
//new String(cs);
|
||||
strSC = new String(sbBA, cs);
|
||||
if (!strNIO.equals(strSC))
|
||||
throw new RuntimeException("new String(cs) failed -> " + cs.name());
|
||||
strSC = new String(ba, cs);
|
||||
if (!strNIO.equals(strSC)) {
|
||||
throw new RuntimeException("new String(cs)/bmp failed -> " + cs.name());
|
||||
}
|
||||
return strSC;
|
||||
}
|
||||
|
||||
static void testSurrogates(Charset cs) throws Throwable {
|
||||
//encode unmappable surrogates
|
||||
CharsetEncoder enc = cs.newEncoder()
|
||||
.onMalformedInput(CodingErrorAction.REPLACE)
|
||||
.onUnmappableCharacter(CodingErrorAction.REPLACE);
|
||||
if (enc instanceof sun.nio.cs.ArrayEncoder &&
|
||||
cs.contains(Charset.forName("ASCII"))) {
|
||||
if (cs.name().equals("UTF-8") || // utf8 handles surrogates
|
||||
|
@ -22,7 +22,7 @@
|
||||
*/
|
||||
|
||||
/* @test
|
||||
@bug 7040220
|
||||
@bug 7040220 8054307
|
||||
@summary Test if StringCoding and NIO result have the same de/encoding result for UTF-8
|
||||
* @run main/othervm/timeout=2000 TestStringCodingUTF8
|
||||
* @key randomness
|
||||
@ -50,6 +50,18 @@ public class TestStringCodingUTF8 {
|
||||
}
|
||||
test(cs, bmp, 0, bmp.length);
|
||||
|
||||
char[] ascii = new char[0x80];
|
||||
for (int i = 0; i < 0x80; i++) {
|
||||
ascii[i] = (char)i;
|
||||
}
|
||||
test(cs, ascii, 0, ascii.length);
|
||||
|
||||
char[] latin1 = new char[0x100];
|
||||
for (int i = 0; i < 0x100; i++) {
|
||||
latin1[i] = (char)i;
|
||||
}
|
||||
test(cs, latin1, 0, latin1.length);
|
||||
|
||||
ArrayList<Integer> list = new ArrayList<>(0x20000);
|
||||
for (int i = 0; i < 0x20000; i++) {
|
||||
list.add(i, i);
|
||||
|
Loading…
Reference in New Issue
Block a user