Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Refactor String model class #119

Merged
merged 3 commits into from
Jul 23, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 51 additions & 22 deletions src/classes/modules/java.base/java/lang/String.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ public final class String

private static final long serialVersionUID = -6849794470754667710L;

static final boolean COMPACT_STRINGS;
static {
COMPACT_STRINGS = true;
}

private static final ObjectStreamField[] serialPersistentFields =
new ObjectStreamField[0];
Expand Down Expand Up @@ -90,7 +94,6 @@ public String(char value[], int offset, int count) {
String proxy=init(value,offset,count);
this.value=proxy.value;
this.coder=proxy.coder;
this.hash=proxy.hash;
}

private native String init(char[] value, int offset, int count);
Expand All @@ -99,7 +102,6 @@ public String(int[] codePoints, int offset, int count) {
String proxy=init(codePoints,offset,count);
this.value=proxy.value;
this.coder=proxy.coder;
this.hash=proxy.hash;
}

private native String init(int[] codePoints, int offset, int count);
Expand All @@ -109,7 +111,6 @@ public String(byte ascii[], int hibyte, int offset, int count) {
String proxy=init(ascii,hibyte,offset,count);
this.value=proxy.value;
this.coder=proxy.coder;
this.hash=proxy.hash;
}

private native String init(byte ascii[], int hibyte, int offset, int count);
Expand All @@ -125,7 +126,6 @@ public String(byte bytes[], int offset, int length, String charsetName){
String proxy=init(bytes,offset,length,charsetName);
this.value=proxy.value;
this.coder=proxy.coder;
this.hash=proxy.hash;
}

private native String init(byte bytes[], int offset, int length, String charsetName);
Expand Down Expand Up @@ -189,17 +189,18 @@ public String(StringBuilder x) {
if (len == 0) {
this.value = "".value;
this.coder = "".coder;
} else {
return;
}
if (COMPACT_STRINGS) {
byte[] val = StringUTF16.compress(value, off, len);
if (val != null) {
this.value = val;
this.coder = LATIN1;
return;
}

this.coder = UTF16;
this.value = StringUTF16.toBytes(value, off, len);
}
this.coder = UTF16;
this.value = StringUTF16.toBytes(value, off, len);
}

@Deprecated
Expand Down Expand Up @@ -234,11 +235,8 @@ native public byte[] getBytes(String charsetName)
throws UnsupportedEncodingException;

public byte[] getBytes(Charset x){
// No Charset model.
if (x == null){
throw new NullPointerException();
}
return StringCoding.encode(x, this.coder, this.value);
if (x == null) throw new NullPointerException();
return StringCoding.encode(x, coder(), value);
}

native public byte[] getBytes();
Expand All @@ -251,6 +249,26 @@ public boolean contentEquals(StringBuffer stringBuffer){
}
}

private boolean nonSyncContentEquals(AbstractStringBuilder abstractStringBuilder) {
int len = length();
if (len != abstractStringBuilder.length()) {
return false;
}
byte v1[] = value;
byte v2[] = abstractStringBuilder.getValue();
if (coder() == abstractStringBuilder.getCoder()) {
int n = v1.length;
for (int i = 0; i < n; i++) {
if (v1[i] != v2[i]) {
return false;
}
}
} else {
return isLatin1() && StringUTF16.contentEquals(v1, v2, len);
}
return true;
}

native static boolean equals0 (char[] a, char[] b, int len);

/**
Expand All @@ -262,21 +280,28 @@ public boolean contentEquals (CharSequence charSequence){
return false;
}

// that should be the common case (String)
if (charSequence.equals(this)){
return true;
// cs is a String
if (charSequence instanceof String) {
return equals(charSequence);
}

// we can do that natively, too
// cs is a StringBuffer, or StringBuilder
if (charSequence instanceof AbstractStringBuilder) {
byte[] val = ((AbstractStringBuilder) charSequence).getValue();
byte coder = ((AbstractStringBuilder) charSequence).getCoder();
assert coder == UTF16 : "Currently only UTF16 is supported for String comparision with an instance of type AbstractStringBuilder";
return StringUTF16.contentEquals(this.value, val, this.length());
if (charSequence instanceof StringBuffer) {
synchronized (charSequence) {
return nonSyncContentEquals((AbstractStringBuilder) charSequence);
}
} else {
return nonSyncContentEquals((AbstractStringBuilder) charSequence);
}
}

// generic CharSequence - expensive
int n = charSequence.length();
if (n != length()) {
return false;
}

byte[] val = this.value;
if (isLatin1()) {
for (int i = 0; i < n; i++) {
Expand Down Expand Up @@ -401,8 +426,12 @@ public static String valueOf(char character) {
native public static String valueOf(double d);
public native String intern();

byte coder() {
return COMPACT_STRINGS ? coder : UTF16;
}

private boolean isLatin1() {
return this.coder == LATIN1;
return COMPACT_STRINGS && coder == LATIN1;
}

/*
Expand Down