Merge pull request #161 from soc/topic/SIOOBE

Add StringIndexOutOfBoundsException and use it in String
This commit is contained in:
Joel Dice 2014-01-22 12:50:46 -08:00
commit ed119938b0
2 changed files with 80 additions and 44 deletions

View File

@ -10,13 +10,14 @@
package java.lang; package java.lang;
import java.io.Serializable;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.util.regex.Pattern;
import java.util.Comparator; import java.util.Comparator;
import java.util.Locale; import java.util.Locale;
import java.io.Serializable; import java.util.regex.Pattern;
import avian.Utf8;
import avian.Iso88591; import avian.Iso88591;
import avian.Utf8;
public final class String public final class String
implements Comparable<String>, CharSequence, Serializable implements Comparable<String>, CharSequence, Serializable
@ -28,6 +29,7 @@ public final class String
public static Comparator<String> CASE_INSENSITIVE_ORDER public static Comparator<String> CASE_INSENSITIVE_ORDER
= new Comparator<String>() { = new Comparator<String>() {
@Override
public int compare(String a, String b) { public int compare(String a, String b) {
return a.compareToIgnoreCase(b); return a.compareToIgnoreCase(b);
} }
@ -64,7 +66,7 @@ public final class String
throw new UnsupportedEncodingException(charsetName); throw new UnsupportedEncodingException(charsetName);
} }
} }
public String(byte[] data, int offset, int length, boolean copy) { public String(byte[] data, int offset, int length, boolean copy) {
this((Object) data, offset, length, copy); this((Object) data, offset, length, copy);
} }
@ -88,10 +90,12 @@ public final class String
} }
public String(byte bytes[], int highByte, int offset, int length) { public String(byte bytes[], int highByte, int offset, int length) {
if (offset < 0 || offset + length > bytes.length) { if (offset < 0 )
throw new IndexOutOfBoundsException throw new StringIndexOutOfBoundsException(offset);
(offset + " < 0 or " + offset + " + " + length + " > " + bytes.length); else if (offset + length > bytes.length)
} throw new StringIndexOutOfBoundsException(offset + length);
else if (length < 0)
throw new StringIndexOutOfBoundsException(length);
char[] c = new char[length]; char[] c = new char[length];
int mask = highByte << 8; int mask = highByte << 8;
@ -112,10 +116,12 @@ public final class String
l = ((byte[]) data).length; l = ((byte[]) data).length;
} }
if (offset < 0 || offset + length > l) { if (offset < 0 )
throw new IndexOutOfBoundsException throw new StringIndexOutOfBoundsException(offset);
(offset + " < 0 or " + offset + " + " + length + " > " + l); else if (offset + length > l)
} throw new StringIndexOutOfBoundsException(offset + length);
else if (length < 0)
throw new StringIndexOutOfBoundsException(length);
if(!copy && Utf8.test(data)) copy = true; if(!copy && Utf8.test(data)) copy = true;
@ -133,7 +139,7 @@ public final class String
+ "\""); + "\"");
} }
} }
this.data = c; this.data = c;
this.offset = 0; this.offset = 0;
this.length = length; this.length = length;
@ -144,14 +150,17 @@ public final class String
} }
} }
@Override
public String toString() { public String toString() {
return this; return this;
} }
@Override
public int length() { public int length() {
return length; return length;
} }
@Override
public int hashCode() { public int hashCode() {
if (hashCode == 0) { if (hashCode == 0) {
int h = 0; int h = 0;
@ -161,6 +170,7 @@ public final class String
return hashCode; return hashCode;
} }
@Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) { if (this == o) {
return true; return true;
@ -172,17 +182,15 @@ public final class String
} }
} }
public boolean equalsIgnoreCase(String o) { public boolean equalsIgnoreCase(String s) {
if (this == o) { if (this == s) {
return true; return true;
} else if (o instanceof String) {
String s = (String) o;
return s.length == length && compareToIgnoreCase(s) == 0;
} else { } else {
return false; return s.length == length && compareToIgnoreCase(s) == 0;
} }
} }
@Override
public int compareTo(String s) { public int compareTo(String s) {
if (this == s) return 0; if (this == s) return 0;
@ -367,18 +375,20 @@ public final class String
} }
public String substring(int start, int end) { public String substring(int start, int end) {
if (start >= 0 && end >= start && end <= length) { if (start < 0)
if (start == 0 && end == length) { throw new StringIndexOutOfBoundsException(start);
return this; else if (end > length)
} else if (end - start == 0) { throw new StringIndexOutOfBoundsException(end);
return ""; int newLen = end - start;
} else { if (newLen < 0)
return new String(data, offset + start, end - start, false); throw new StringIndexOutOfBoundsException(newLen);
}
} else { if (start == 0 && end == length)
throw new IndexOutOfBoundsException return this;
(start + " not in [0, " + end + ") or " + end + " > " + length); else if (end - start == 0)
} return "";
else
return new String(data, offset + start, newLen, false);
} }
public boolean startsWith(String s) { public boolean startsWith(String s) {
@ -396,7 +406,7 @@ public final class String
return false; return false;
} }
} }
public boolean endsWith(String s) { public boolean endsWith(String s) {
if (length >= s.length) { if (length >= s.length) {
return substring(length - s.length).compareTo(s) == 0; return substring(length - s.length).compareTo(s) == 0;
@ -416,9 +426,12 @@ public final class String
public void getBytes(int srcOffset, int srcLength, public void getBytes(int srcOffset, int srcLength,
byte[] dst, int dstOffset) byte[] dst, int dstOffset)
{ {
if (srcOffset < 0 || srcOffset + srcLength > length) { if (srcOffset < 0)
throw new IndexOutOfBoundsException(); throw new StringIndexOutOfBoundsException(srcOffset);
} else if (srcOffset + srcLength > length)
throw new StringIndexOutOfBoundsException(srcOffset + srcLength);
else if (srcLength < 0)
throw new StringIndexOutOfBoundsException(srcLength);
if (data instanceof char[]) { if (data instanceof char[]) {
char[] src = (char[]) data; char[] src = (char[]) data;
@ -462,9 +475,11 @@ public final class String
public void getChars(int srcOffset, int srcEnd, public void getChars(int srcOffset, int srcEnd,
char[] dst, int dstOffset) char[] dst, int dstOffset)
{ {
if (srcOffset < 0 || srcEnd > length) { if (srcOffset < 0)
throw new IndexOutOfBoundsException(); throw new StringIndexOutOfBoundsException(srcOffset);
} else if (srcEnd > length)
throw new StringIndexOutOfBoundsException(srcEnd);
int srcLength = srcEnd-srcOffset; int srcLength = srcEnd-srcOffset;
if (data instanceof char[]) { if (data instanceof char[]) {
char[] src = (char[]) data; char[] src = (char[]) data;
@ -473,7 +488,7 @@ public final class String
byte[] src = (byte[]) data; byte[] src = (byte[]) data;
for (int i = 0; i < srcLength; ++i) { for (int i = 0; i < srcLength; ++i) {
dst[i + dstOffset] = (char) src[i + offset + srcOffset]; dst[i + dstOffset] = (char) src[i + offset + srcOffset];
} }
} }
} }
@ -483,11 +498,12 @@ public final class String
return b; return b;
} }
@Override
public char charAt(int index) { public char charAt(int index) {
if (index < 0 || index > length) { if (index < 0 || index > length) {
throw new IndexOutOfBoundsException(); throw new StringIndexOutOfBoundsException(index);
} }
if (data instanceof char[]) { if (data instanceof char[]) {
return ((char[]) data)[index + offset]; return ((char[]) data)[index + offset];
} else { } else {
@ -503,10 +519,11 @@ public final class String
return Pattern.compile(regex).split(this, limit); return Pattern.compile(regex).split(this, limit);
} }
@Override
public CharSequence subSequence(int start, int end) { public CharSequence subSequence(int start, int end) {
return substring(start, end); return substring(start, end);
} }
public boolean matches(String regex) { public boolean matches(String regex) {
return Pattern.matches(regex, this); return Pattern.matches(regex, this);
} }
@ -514,7 +531,7 @@ public final class String
public String replaceFirst(String regex, String replacement) { public String replaceFirst(String regex, String replacement) {
return Pattern.compile(regex).matcher(this).replaceFirst(replacement); return Pattern.compile(regex).matcher(this).replaceFirst(replacement);
} }
public String replaceAll(String regex, String replacement) { public String replaceAll(String regex, String replacement) {
return Pattern.compile(regex).matcher(this).replaceAll(replacement); return Pattern.compile(regex).matcher(this).replaceAll(replacement);
} }
@ -554,7 +571,7 @@ public final class String
retVal.append(infuseWith); retVal.append(infuseWith);
return retVal.toString(); return retVal.toString();
} }
public native String intern(); public native String intern();
public static String valueOf(Object s) { public static String valueOf(Object s) {

View File

@ -0,0 +1,19 @@
package java.lang;
/**
* Used by <code>String</code> to signal that a given index is either less than
* or greater than the allowed range.
*/
public class StringIndexOutOfBoundsException extends IndexOutOfBoundsException {
private static final long serialVersionUID = -6762910422159637258L;
public StringIndexOutOfBoundsException(int index) {
super("String index out of range: "+index);
}
public StringIndexOutOfBoundsException(String message) {
super(message);
}
public StringIndexOutOfBoundsException() {}
}