8055251: Re-examine Integer.parseInt and Long.parseLong methods

Reviewed-by: alanb
This commit is contained in:
Claes Redestad 2014-09-10 13:51:17 +01:00 committed by Alan Bateman
parent d04d69fea6
commit 1dc4b5e2f8
9 changed files with 147 additions and 309 deletions

View file

@ -592,37 +592,6 @@ public final class Integer extends Number implements Comparable<Integer> {
} }
} }
/**
* Parses the {@link CharSequence} argument as a signed {@code int} in the
* specified {@code radix}, beginning at the specified {@code beginIndex}
* and extending to the end of the sequence.
*
* <p>The method does not take steps to guard against the
* {@code CharSequence} being mutated while parsing.
*
* @param s the {@code CharSequence} containing the {@code int}
* representation to be parsed
* @param radix the radix to be used while parsing {@code s}.
* @param beginIndex the beginning index, inclusive.
* @return the signed {@code int} represented by the subsequence in
* the specified radix.
* @throws NullPointerException if {@code s} is null.
* @throws IndexOutOfBoundsException if {@code beginIndex} is
* negative, or if {@code beginIndex} is greater than
* {@code s.length()}.
* @throws NumberFormatException if the {@code CharSequence} does not
* contain a parsable {@code int} in the specified
* {@code radix}, or if {@code radix} is either smaller than
* {@link java.lang.Character#MIN_RADIX} or larger than
* {@link java.lang.Character#MAX_RADIX}.
* @since 1.9
*/
public static int parseInt(CharSequence s, int radix, int beginIndex)
throws NumberFormatException {
// forces an implicit null check of s
return parseInt(s, radix, beginIndex, s.length());
}
/** /**
* Parses the {@link CharSequence} argument as a signed {@code int} in the * Parses the {@link CharSequence} argument as a signed {@code int} in the
* specified {@code radix}, beginning at the specified {@code beginIndex} * specified {@code radix}, beginning at the specified {@code beginIndex}
@ -633,9 +602,9 @@ public final class Integer extends Number implements Comparable<Integer> {
* *
* @param s the {@code CharSequence} containing the {@code int} * @param s the {@code CharSequence} containing the {@code int}
* representation to be parsed * representation to be parsed
* @param radix the radix to be used while parsing {@code s}.
* @param beginIndex the beginning index, inclusive. * @param beginIndex the beginning index, inclusive.
* @param endIndex the ending index, exclusive. * @param endIndex the ending index, exclusive.
* @param radix the radix to be used while parsing {@code s}.
* @return the signed {@code int} represented by the subsequence in * @return the signed {@code int} represented by the subsequence in
* the specified radix. * the specified radix.
* @throws NullPointerException if {@code s} is null. * @throws NullPointerException if {@code s} is null.
@ -650,7 +619,7 @@ public final class Integer extends Number implements Comparable<Integer> {
* {@link java.lang.Character#MAX_RADIX}. * {@link java.lang.Character#MAX_RADIX}.
* @since 1.9 * @since 1.9
*/ */
public static int parseInt(CharSequence s, int radix, int beginIndex, int endIndex) public static int parseInt(CharSequence s, int beginIndex, int endIndex, int radix)
throws NumberFormatException { throws NumberFormatException {
s = Objects.requireNonNull(s); s = Objects.requireNonNull(s);
@ -690,7 +659,7 @@ public final class Integer extends Number implements Comparable<Integer> {
int result = 0; int result = 0;
while (i < endIndex) { while (i < endIndex) {
// Accumulating negatively avoids surprises near MAX_VALUE // Accumulating negatively avoids surprises near MAX_VALUE
int digit = Character.digit(s.charAt(i++), radix); int digit = Character.digit(s.charAt(i), radix);
if (digit < 0 || result < multmin) { if (digit < 0 || result < multmin) {
throw NumberFormatException.forCharSequence(s, beginIndex, throw NumberFormatException.forCharSequence(s, beginIndex,
endIndex, i); endIndex, i);
@ -700,6 +669,7 @@ public final class Integer extends Number implements Comparable<Integer> {
throw NumberFormatException.forCharSequence(s, beginIndex, throw NumberFormatException.forCharSequence(s, beginIndex,
endIndex, i); endIndex, i);
} }
i++;
result -= digit; result -= digit;
} }
return negative ? result : -result; return negative ? result : -result;
@ -805,37 +775,6 @@ public final class Integer extends Number implements Comparable<Integer> {
} }
} }
/**
* Parses the {@link CharSequence} argument as an unsigned {@code int} in
* the specified {@code radix}, beginning at the specified
* {@code beginIndex} and extending to the end of the sequence.
*
* <p>The method does not take steps to guard against the
* {@code CharSequence} being mutated while parsing.
*
* @param s the {@code CharSequence} containing the unsigned
* {@code int} representation to be parsed
* @param radix the radix to be used while parsing {@code s}.
* @param beginIndex the beginning index, inclusive.
* @return the unsigned {@code int} represented by the subsequence in
* the specified radix.
* @throws NullPointerException if {@code s} is null.
* @throws IndexOutOfBoundsException if {@code beginIndex} is
* negative, or if {@code beginIndex} is greater than
* {@code s.length()}.
* @throws NumberFormatException if the {@code CharSequence} does not
* contain a parsable unsigned {@code int} in the specified
* {@code radix}, or if {@code radix} is either smaller than
* {@link java.lang.Character#MIN_RADIX} or larger than
* {@link java.lang.Character#MAX_RADIX}.
* @since 1.9
*/
public static int parseUnsignedInt(CharSequence s, int radix, int beginIndex)
throws NumberFormatException {
// forces an implicit null check of s
return parseUnsignedInt(s, radix, beginIndex, s.length());
}
/** /**
* Parses the {@link CharSequence} argument as an unsigned {@code int} in * Parses the {@link CharSequence} argument as an unsigned {@code int} in
* the specified {@code radix}, beginning at the specified * the specified {@code radix}, beginning at the specified
@ -846,9 +785,9 @@ public final class Integer extends Number implements Comparable<Integer> {
* *
* @param s the {@code CharSequence} containing the unsigned * @param s the {@code CharSequence} containing the unsigned
* {@code int} representation to be parsed * {@code int} representation to be parsed
* @param radix the radix to be used while parsing {@code s}.
* @param beginIndex the beginning index, inclusive. * @param beginIndex the beginning index, inclusive.
* @param endIndex the ending index, exclusive. * @param endIndex the ending index, exclusive.
* @param radix the radix to be used while parsing {@code s}.
* @return the unsigned {@code int} represented by the subsequence in * @return the unsigned {@code int} represented by the subsequence in
* the specified radix. * the specified radix.
* @throws NullPointerException if {@code s} is null. * @throws NullPointerException if {@code s} is null.
@ -863,7 +802,7 @@ public final class Integer extends Number implements Comparable<Integer> {
* {@link java.lang.Character#MAX_RADIX}. * {@link java.lang.Character#MAX_RADIX}.
* @since 1.9 * @since 1.9
*/ */
public static int parseUnsignedInt(CharSequence s, int radix, int beginIndex, int endIndex) public static int parseUnsignedInt(CharSequence s, int beginIndex, int endIndex, int radix)
throws NumberFormatException { throws NumberFormatException {
s = Objects.requireNonNull(s); s = Objects.requireNonNull(s);
@ -881,9 +820,9 @@ public final class Integer extends Number implements Comparable<Integer> {
} else { } else {
if (len <= 5 || // Integer.MAX_VALUE in Character.MAX_RADIX is 6 digits if (len <= 5 || // Integer.MAX_VALUE in Character.MAX_RADIX is 6 digits
(radix == 10 && len <= 9)) { // Integer.MAX_VALUE in base 10 is 10 digits (radix == 10 && len <= 9)) { // Integer.MAX_VALUE in base 10 is 10 digits
return parseInt(s, radix, start, start + len); return parseInt(s, start, start + len, radix);
} else { } else {
long ell = Long.parseLong(s, radix, start, start + len); long ell = Long.parseLong(s, start, start + len, radix);
if ((ell & 0xffff_ffff_0000_0000L) == 0) { if ((ell & 0xffff_ffff_0000_0000L) == 0) {
return (int) ell; return (int) ell;
} else { } else {

View file

@ -604,37 +604,6 @@ public final class Long extends Number implements Comparable<Long> {
} }
} }
/**
* Parses the {@link CharSequence} argument as a signed {@code long} in
* the specified {@code radix}, beginning at the specified {@code beginIndex}
* and extending to the end of the sequence.
*
* <p>The method does not take steps to guard against the
* {@code CharSequence} being mutated while parsing.
*
* @param s the {@code CharSequence} containing the {@code long}
* representation to be parsed
* @param radix the radix to be used while parsing {@code s}.
* @param beginIndex the beginning index, inclusive.
* @return the signed {@code long} represented by the subsequence in
* the specified radix.
* @throws NullPointerException if {@code s} is null.
* @throws IndexOutOfBoundsException if {@code beginIndex} is
* negative, or if {@code beginIndex} is greater than
* {@code s.length()}.
* @throws NumberFormatException if the {@code CharSequence} does not
* contain a parsable {@code long} in the specified
* {@code radix}, or if {@code radix} is either smaller than
* {@link java.lang.Character#MIN_RADIX} or larger than
* {@link java.lang.Character#MAX_RADIX}.
* @since 1.9
*/
public static long parseLong(CharSequence s, int radix, int beginIndex)
throws NumberFormatException {
// forces a null check of s
return parseLong(s, radix, beginIndex, s.length());
}
/** /**
* Parses the {@link CharSequence} argument as a signed {@code long} in * Parses the {@link CharSequence} argument as a signed {@code long} in
* the specified {@code radix}, beginning at the specified * the specified {@code radix}, beginning at the specified
@ -645,9 +614,9 @@ public final class Long extends Number implements Comparable<Long> {
* *
* @param s the {@code CharSequence} containing the {@code long} * @param s the {@code CharSequence} containing the {@code long}
* representation to be parsed * representation to be parsed
* @param radix the radix to be used while parsing {@code s}.
* @param beginIndex the beginning index, inclusive. * @param beginIndex the beginning index, inclusive.
* @param endIndex the ending index, exclusive. * @param endIndex the ending index, exclusive.
* @param radix the radix to be used while parsing {@code s}.
* @return the signed {@code long} represented by the subsequence in * @return the signed {@code long} represented by the subsequence in
* the specified radix. * the specified radix.
* @throws NullPointerException if {@code s} is null. * @throws NullPointerException if {@code s} is null.
@ -662,7 +631,7 @@ public final class Long extends Number implements Comparable<Long> {
* {@link java.lang.Character#MAX_RADIX}. * {@link java.lang.Character#MAX_RADIX}.
* @since 1.9 * @since 1.9
*/ */
public static long parseLong(CharSequence s, int radix, int beginIndex, int endIndex) public static long parseLong(CharSequence s, int beginIndex, int endIndex, int radix)
throws NumberFormatException { throws NumberFormatException {
s = Objects.requireNonNull(s); s = Objects.requireNonNull(s);
@ -702,7 +671,7 @@ public final class Long extends Number implements Comparable<Long> {
long result = 0; long result = 0;
while (i < endIndex) { while (i < endIndex) {
// Accumulating negatively avoids surprises near MAX_VALUE // Accumulating negatively avoids surprises near MAX_VALUE
int digit = Character.digit(s.charAt(i++), radix); int digit = Character.digit(s.charAt(i), radix);
if (digit < 0 || result < multmin) { if (digit < 0 || result < multmin) {
throw NumberFormatException.forCharSequence(s, beginIndex, throw NumberFormatException.forCharSequence(s, beginIndex,
endIndex, i); endIndex, i);
@ -712,6 +681,7 @@ public final class Long extends Number implements Comparable<Long> {
throw NumberFormatException.forCharSequence(s, beginIndex, throw NumberFormatException.forCharSequence(s, beginIndex,
endIndex, i); endIndex, i);
} }
i++;
result -= digit; result -= digit;
} }
return negative ? result : -result; return negative ? result : -result;
@ -811,7 +781,7 @@ public final class Long extends Number implements Comparable<Long> {
} }
// No need for range checks on len due to testing above. // No need for range checks on len due to testing above.
long first = parseLong(s, radix, 0, len - 1); long first = parseLong(s, 0, len - 1, radix);
int second = Character.digit(s.charAt(len - 1), radix); int second = Character.digit(s.charAt(len - 1), radix);
if (second < 0) { if (second < 0) {
throw new NumberFormatException("Bad digit at end of " + s); throw new NumberFormatException("Bad digit at end of " + s);
@ -880,37 +850,6 @@ public final class Long extends Number implements Comparable<Long> {
} }
} }
/**
* Parses the {@link CharSequence} argument as an unsigned {@code long} in
* the specified {@code radix}, beginning at the specified
* {@code beginIndex} and extending to the end of the sequence.
*
* <p>The method does not take steps to guard against the
* {@code CharSequence} being mutated while parsing.
*
* @param s the {@code CharSequence} containing the unsigned
* {@code long} representation to be parsed
* @param radix the radix to be used while parsing {@code s}.
* @param beginIndex the beginning index, inclusive.
* @return the unsigned {@code long} represented by the subsequence in
* the specified radix.
* @throws NullPointerException if {@code s} is null.
* @throws IndexOutOfBoundsException if {@code beginIndex} is
* negative, or if {@code beginIndex} is greater than
* {@code s.length()}.
* @throws NumberFormatException if the {@code CharSequence} does not
* contain a parsable unsigned {@code long} in the specified
* {@code radix}, or if {@code radix} is either smaller than
* {@link java.lang.Character#MIN_RADIX} or larger than
* {@link java.lang.Character#MAX_RADIX}.
* @since 1.9
*/
public static long parseUnsignedLong(CharSequence s, int radix, int beginIndex)
throws NumberFormatException {
// forces a null check of s
return parseUnsignedLong(s, radix, beginIndex, s.length());
}
/** /**
* Parses the {@link CharSequence} argument as an unsigned {@code long} in * Parses the {@link CharSequence} argument as an unsigned {@code long} in
* the specified {@code radix}, beginning at the specified * the specified {@code radix}, beginning at the specified
@ -921,9 +860,9 @@ public final class Long extends Number implements Comparable<Long> {
* *
* @param s the {@code CharSequence} containing the unsigned * @param s the {@code CharSequence} containing the unsigned
* {@code long} representation to be parsed * {@code long} representation to be parsed
* @param radix the radix to be used while parsing {@code s}.
* @param beginIndex the beginning index, inclusive. * @param beginIndex the beginning index, inclusive.
* @param endIndex the ending index, exclusive. * @param endIndex the ending index, exclusive.
* @param radix the radix to be used while parsing {@code s}.
* @return the unsigned {@code long} represented by the subsequence in * @return the unsigned {@code long} represented by the subsequence in
* the specified radix. * the specified radix.
* @throws NullPointerException if {@code s} is null. * @throws NullPointerException if {@code s} is null.
@ -938,7 +877,7 @@ public final class Long extends Number implements Comparable<Long> {
* {@link java.lang.Character#MAX_RADIX}. * {@link java.lang.Character#MAX_RADIX}.
* @since 1.9 * @since 1.9
*/ */
public static long parseUnsignedLong(CharSequence s, int radix, int beginIndex, int endIndex) public static long parseUnsignedLong(CharSequence s, int beginIndex, int endIndex, int radix)
throws NumberFormatException { throws NumberFormatException {
s = Objects.requireNonNull(s); s = Objects.requireNonNull(s);
@ -955,11 +894,11 @@ public final class Long extends Number implements Comparable<Long> {
} else { } else {
if (len <= 12 || // Long.MAX_VALUE in Character.MAX_RADIX is 13 digits if (len <= 12 || // Long.MAX_VALUE in Character.MAX_RADIX is 13 digits
(radix == 10 && len <= 18) ) { // Long.MAX_VALUE in base 10 is 19 digits (radix == 10 && len <= 18) ) { // Long.MAX_VALUE in base 10 is 19 digits
return parseLong(s, radix, start, start + len); return parseLong(s, start, start + len, radix);
} }
// No need for range checks on end due to testing above. // No need for range checks on end due to testing above.
long first = parseLong(s, radix, start, start + len - 1); long first = parseLong(s, start, start + len - 1, radix);
int second = Character.digit(s.charAt(start + len - 1), radix); int second = Character.digit(s.charAt(start + len - 1), radix);
if (second < 0) { if (second < 0) {
throw new NumberFormatException("Bad digit at end of " + throw new NumberFormatException("Bad digit at end of " +

View file

@ -424,7 +424,7 @@ public final class Duration
return 0; return 0;
} }
try { try {
long val = Long.parseLong(text, 10, start, end); long val = Long.parseLong(text, start, end, 10);
return Math.multiplyExact(val, multiplier); return Math.multiplyExact(val, multiplier);
} catch (NumberFormatException | ArithmeticException ex) { } catch (NumberFormatException | ArithmeticException ex) {
throw (DateTimeParseException) new DateTimeParseException("Text cannot be parsed to a Duration: " + errorText, text, 0).initCause(ex); throw (DateTimeParseException) new DateTimeParseException("Text cannot be parsed to a Duration: " + errorText, text, 0).initCause(ex);
@ -437,7 +437,7 @@ public final class Duration
return 0; return 0;
} }
try { try {
int fraction = Integer.parseInt(text, 10, start, end); int fraction = Integer.parseInt(text, start, end, 10);
// for number strings smaller than 9 digits, interpret as if there // for number strings smaller than 9 digits, interpret as if there
// were trailing zeros // were trailing zeros

View file

@ -358,7 +358,7 @@ public final class Period
if (start < 0 || end < 0) { if (start < 0 || end < 0) {
return 0; return 0;
} }
int val = Integer.parseInt(text, 10, start, end); int val = Integer.parseInt(text, start, end, 10);
try { try {
return Math.multiplyExact(val, negate); return Math.multiplyExact(val, negate);
} catch (ArithmeticException ex) { } catch (ArithmeticException ex) {

View file

@ -194,7 +194,8 @@ public final class UUID implements java.io.Serializable, Comparable<UUID> {
* *
*/ */
public static UUID fromString(String name) { public static UUID fromString(String name) {
if (name.length() > 36) { int len = name.length();
if (len > 36) {
throw new IllegalArgumentException("UUID string too large"); throw new IllegalArgumentException("UUID string too large");
} }
@ -214,15 +215,14 @@ public final class UUID implements java.io.Serializable, Comparable<UUID> {
throw new IllegalArgumentException("Invalid UUID string: " + name); throw new IllegalArgumentException("Invalid UUID string: " + name);
} }
long mostSigBits = Long.parseLong(name, 16, 0, dash1) & 0xffffffffL; long mostSigBits = Long.parseLong(name, 0, dash1, 16) & 0xffffffffL;
mostSigBits <<= 16; mostSigBits <<= 16;
mostSigBits |= Long.parseLong(name, 16, dash1 + 1, dash2) & 0xffffL; mostSigBits |= Long.parseLong(name, dash1 + 1, dash2, 16) & 0xffffL;
mostSigBits <<= 16; mostSigBits <<= 16;
mostSigBits |= Long.parseLong(name, 16, dash2 + 1, dash3) & 0xffffL; mostSigBits |= Long.parseLong(name, dash2 + 1, dash3, 16) & 0xffffL;
long leastSigBits = Long.parseLong(name, dash3 + 1, dash4, 16) & 0xffffL;
long leastSigBits = Long.parseLong(name, 16, dash3 + 1, dash4) & 0xffffL;
leastSigBits <<= 48; leastSigBits <<= 48;
leastSigBits |= Long.parseLong(name, 16, dash4 + 1) & 0xffffffffffffL; leastSigBits |= Long.parseLong(name, dash4 + 1, len, 16) & 0xffffffffffffL;
return new UUID(mostSigBits, leastSigBits); return new UUID(mostSigBits, leastSigBits);
} }

View file

@ -23,24 +23,22 @@
/* /*
* @test * @test
* @bug 5017980 6576055 8041972 * @bug 5017980 6576055 8041972 8055251
* @summary Test parsing methods * @summary Test parsing methods
* @author Joseph D. Darcy * @author Joseph D. Darcy
*/ */
import java.lang.IllegalArgumentException;
import java.lang.IndexOutOfBoundsException; import java.lang.IndexOutOfBoundsException;
import java.lang.NullPointerException; import java.lang.NullPointerException;
import java.lang.RuntimeException; import java.lang.RuntimeException;
/** /**
* There are eight methods in java.lang.Integer which transform strings * There are seven methods in java.lang.Integer which transform strings
* into an int or Integer value: * into an int or Integer value:
* *
* public Integer(String s) * public Integer(String s)
* public static Integer decode(String nm) * public static Integer decode(String nm)
* public static int parseInt(CharSequence s, int radix, int beginIndex, int endIndex) * public static int parseInt(CharSequence s, int beginIndex, int endIndex, int radix)
* public static int parseInt(CharSequence s, int radix, int beginIndex)
* public static int parseInt(String s, int radix) * public static int parseInt(String s, int radix)
* public static int parseInt(String s) * public static int parseInt(String s)
* public static Integer valueOf(String s, int radix) * public static Integer valueOf(String s, int radix)
@ -55,20 +53,17 @@ import java.lang.RuntimeException;
public class ParsingTest { public class ParsingTest {
public static void main(String... argv) { public static void main(String... argv) {
check("+100", +100); check(+100, "+100");
check("-100", -100); check(-100, "-100");
check("+0", 0); check(0, "+0");
check("-0", 0); check(0, "-0");
check("+00000", 0); check(0, "+00000");
check("-00000", 0); check(0, "-00000");
check("+00000", 0, 0, 6); check(0, "0");
check("-00000", 0, 0, 6); check(1, "1");
check(9, "9");
check("0", 0);
check("1", 1);
check("9", 9);
checkFailure(""); checkFailure("");
checkFailure("\u0000"); checkFailure("\u0000");
@ -85,41 +80,37 @@ public class ParsingTest {
checkFailure("-+6"); checkFailure("-+6");
checkFailure("*100"); checkFailure("*100");
check("test-00000", 0, 4, 10); // check offset based methods
check("test-12345", -12345, 4, 10); check(0, "+00000", 0, 6, 10);
check("xx12345yy", 12345, 2, 7); check(0, "-00000", 0, 6, 10);
check(0, "test-00000", 4, 10, 10);
check(-12345, "test-12345", 4, 10, 10);
check(12345, "xx12345yy", 2, 7, 10);
check(15, "xxFyy", 2, 3, 16);
checkNumberFormatException("", 10, 0); checkNumberFormatException("", 0, 0, 10);
checkNumberFormatException("100", 10, 3); checkNumberFormatException("+-6", 0, 3, 10);
checkNumberFormatException("+1000000", 10, 8); checkNumberFormatException("1000000", 7, 7, 10);
checkNumberFormatException("-1000000", 10, 8); checkNumberFormatException("1000000", 0, 2, Character.MAX_RADIX + 1);
checkNumberFormatException("1000000", 0, 2, Character.MIN_RADIX - 1);
checkNumberFormatException("", 10, 0, 0); checkIndexOutOfBoundsException("1000000", 10, 4, 10);
checkNumberFormatException("+-6", 10, 0, 3); checkIndexOutOfBoundsException("1000000", -1, 2, Character.MAX_RADIX + 1);
checkNumberFormatException("1000000", 10, 7); checkIndexOutOfBoundsException("1000000", -1, 2, Character.MIN_RADIX - 1);
checkNumberFormatException("1000000", 10, 7, 7); checkIndexOutOfBoundsException("1000000", 10, 2, Character.MAX_RADIX + 1);
checkNumberFormatException("1000000", Character.MAX_RADIX + 1, 0, 2); checkIndexOutOfBoundsException("1000000", 10, 2, Character.MIN_RADIX - 1);
checkNumberFormatException("1000000", Character.MIN_RADIX - 1, 0, 2); checkIndexOutOfBoundsException("-1", 0, 3, 10);
checkIndexOutOfBoundsException("-1", 2, 3, 10);
checkIndexOutOfBoundsException("-1", -1, 2, 10);
checkIndexOutOfBoundsException("1000000", 10, 8); checkNull(0, 1, 10);
checkIndexOutOfBoundsException("1000000", 10, -1); checkNull(-1, 0, 10);
checkIndexOutOfBoundsException("1000000", 10, 10, 4); checkNull(0, 0, 10);
checkIndexOutOfBoundsException("1000000", Character.MAX_RADIX + 1, -1, 2); checkNull(0, -1, 10);
checkIndexOutOfBoundsException("1000000", Character.MIN_RADIX - 1, -1, 2);
checkIndexOutOfBoundsException("1000000", Character.MAX_RADIX + 1, 10, 2);
checkIndexOutOfBoundsException("1000000", Character.MIN_RADIX - 1, 10, 2);
checkIndexOutOfBoundsException("-1", 10, 0, 3);
checkIndexOutOfBoundsException("-1", 10, 2, 3);
checkIndexOutOfBoundsException("-1", 10, -1, 2);
checkNull(10, 0, 1);
checkNull(10, -1, 0);
checkNull(10, 0, 0);
checkNull(10, 0, -1);
checkNull(-1, -1, -1); checkNull(-1, -1, -1);
} }
private static void check(String val, int expected) { private static void check(int expected, String val) {
int n = Integer.parseInt(val); int n = Integer.parseInt(val);
if (n != expected) if (n != expected)
throw new RuntimeException("Integer.parseInt failed. String:" + throw new RuntimeException("Integer.parseInt failed. String:" +
@ -137,11 +128,11 @@ public class ParsingTest {
} }
} }
private static void checkNumberFormatException(String val, int radix, int start) { private static void checkNumberFormatException(String val, int start, int end, int radix) {
int n = 0; int n = 0;
try { try {
n = Integer.parseInt(val, radix, start); n = Integer.parseInt(val, start, end, radix);
System.err.println("parseInt(" + val + ", " + radix + ", " + start + System.err.println("parseInt(" + val + ", " + start + ", " + end + ", " + radix +
") incorrectly returned " + n); ") incorrectly returned " + n);
throw new RuntimeException(); throw new RuntimeException();
} catch (NumberFormatException nfe) { } catch (NumberFormatException nfe) {
@ -149,23 +140,11 @@ public class ParsingTest {
} }
} }
private static void checkNumberFormatException(String val, int radix, int start, int end) { private static void checkIndexOutOfBoundsException(String val, int start, int end, int radix) {
int n = 0; int n = 0;
try { try {
n = Integer.parseInt(val, radix, start, end); n = Integer.parseInt(val, start, end, radix);
System.err.println("parseInt(" + val + ", " + radix + ", " + start + ", " + end + System.err.println("parseInt(" + val + ", " + start + ", " + end + ", " + radix +
") incorrectly returned " + n);
throw new RuntimeException();
} catch (NumberFormatException nfe) {
; // Expected
}
}
private static void checkIndexOutOfBoundsException(String val, int radix, int start) {
int n = 0;
try {
n = Integer.parseInt(val, radix, start);
System.err.println("parseInt(" + val + ", " + radix + ", " + start +
") incorrectly returned " + n); ") incorrectly returned " + n);
throw new RuntimeException(); throw new RuntimeException();
} catch (IndexOutOfBoundsException ioob) { } catch (IndexOutOfBoundsException ioob) {
@ -173,23 +152,11 @@ public class ParsingTest {
} }
} }
private static void checkIndexOutOfBoundsException(String val, int radix, int start, int end) { private static void checkNull(int start, int end, int radix) {
int n = 0; int n = 0;
try { try {
n = Integer.parseInt(val, radix, start, end); n = Integer.parseInt(null, start, end, radix);
System.err.println("parseInt(" + val + ", " + radix + ", " + start + ", " + end + System.err.println("parseInt(null, " + start + ", " + end + ", " + radix +
") incorrectly returned " + n);
throw new RuntimeException();
} catch (IndexOutOfBoundsException ioob) {
; // Expected
}
}
private static void checkNull(int radix, int start, int end) {
int n = 0;
try {
n = Integer.parseInt(null, 10, start, end);
System.err.println("parseInt(null, " + radix + ", " + start + ", " + end +
") incorrectly returned " + n); ") incorrectly returned " + n);
throw new RuntimeException(); throw new RuntimeException();
} catch (NullPointerException npe) { } catch (NullPointerException npe) {
@ -197,10 +164,10 @@ public class ParsingTest {
} }
} }
private static void check(String val, int expected, int start, int end) { private static void check(int expected, String val, int start, int end, int radix) {
int n = Integer.parseInt(val, 10, start, end); int n = Integer.parseInt(val, start, end, radix);
if (n != expected) if (n != expected)
throw new RuntimeException("Integer.parsedInt failed. String:" + throw new RuntimeException("Integer.parsedInt failed. Expected: " + expected + " String: \"" +
val + ", start: " + start + ", end: " + end + " Result:" + n); val + "\", start: " + start + ", end: " + end + ", radix: " + radix + " Result:" + n);
} }
} }

View file

@ -303,6 +303,17 @@ public class Unsigned {
"\tconverting back ''%s'' resulted in %d%n", "\tconverting back ''%s'' resulted in %d%n",
value, radix, longString, intResult); value, radix, longString, intResult);
} }
// test offset based parse method
intResult = Integer.parseUnsignedInt("prefix" + longString + "suffix",
"prefix".length(), "prefix".length() + longString.length(), radix);
if (Integer.toUnsignedLong(intResult) != value) {
errors++;
System.err.printf("Bad roundtrip conversion of %d in base %d" +
"\tconverting back ''%s'' resulted in %d%n",
value, radix, longString, intResult);
}
} }
} }

View file

@ -23,19 +23,18 @@
/* /*
* @test * @test
* @bug 5017980 6576055 8041972 * @bug 5017980 6576055 8041972 8055251
* @summary Test parsing methods * @summary Test parsing methods
* @author Joseph D. Darcy * @author Joseph D. Darcy
*/ */
/** /**
* There are eight methods in java.lang.Long which transform strings * There are seven methods in java.lang.Long which transform strings
* into a long or Long value: * into a long or Long value:
* *
* public Long(String s) * public Long(String s)
* public static Long decode(String nm) * public static Long decode(String nm)
* public static long parseLong(CharSequence s, int radix, int beginIndex, int endIndex) * public static long parseLong(CharSequence s, int radix, int beginIndex, int endIndex)
* public static long parseLong(CharSequence s, int radix, int beginIndex)
* public static long parseLong(String s, int radix) * public static long parseLong(String s, int radix)
* public static long parseLong(String s) * public static long parseLong(String s)
* public static Long valueOf(String s, int radix) * public static Long valueOf(String s, int radix)
@ -49,17 +48,17 @@
public class ParsingTest { public class ParsingTest {
public static void main(String... argv) { public static void main(String... argv) {
check("+100", +100L); check(+100L, "+100");
check("-100", -100L); check(-100L, "-100");
check("+0", 0L); check(0L, "+0");
check("-0", 0L); check(0L, "-0");
check("+00000", 0L); check(0L, "+00000");
check("-00000", 0L); check(0L, "-00000");
check("0", 0L); check(0L, "0");
check("1", 1L); check(1L, "1");
check("9", 9L); check(9L, "9");
checkFailure(""); checkFailure("");
checkFailure("\u0000"); checkFailure("\u0000");
@ -76,40 +75,36 @@ public class ParsingTest {
checkFailure("-+6"); checkFailure("-+6");
checkFailure("*100"); checkFailure("*100");
check("test-00000", 0L, 4, 10); check(0L, "test-00000", 4, 10, 10);
check("test-12345", -12345L, 4, 10); check(-12345L, "test-12345", 4, 10, 10);
check("xx12345yy", 12345L, 2, 7); check(12345L, "xx12345yy", 2, 7, 10);
check("xx123456789012345yy", 123456789012345L, 2, 17); check(123456789012345L, "xx123456789012345yy", 2, 17, 10);
check(15L, "xxFyy", 2, 3, 16);
checkNumberFormatException("100", 10, 3); checkNumberFormatException("", 0, 0, 10);
checkNumberFormatException("", 10, 0); checkNumberFormatException("+-6", 0, 3, 10);
checkNumberFormatException("+1000000", 10, 8); checkNumberFormatException("1000000", 7, 7, 10);
checkNumberFormatException("-1000000", 10, 8); checkNumberFormatException("1000000", 0, 2, Character.MAX_RADIX + 1);
checkNumberFormatException("1000000", 0, 2, Character.MIN_RADIX - 1);
checkNumberFormatException("", 10, 0, 0); checkIndexOutOfBoundsException("", 1, 1, 10);
checkNumberFormatException("+-6", 10, 0, 3); checkIndexOutOfBoundsException("1000000", 10, 4, 10);
checkNumberFormatException("1000000", 10, 7, 7); checkIndexOutOfBoundsException("1000000", 10, 2, Character.MAX_RADIX + 1);
checkNumberFormatException("1000000", Character.MAX_RADIX + 1, 0, 2); checkIndexOutOfBoundsException("1000000", 10, 2, Character.MIN_RADIX - 1);
checkNumberFormatException("1000000", Character.MIN_RADIX - 1, 0, 2); checkIndexOutOfBoundsException("1000000", -1, 2, Character.MAX_RADIX + 1);
checkIndexOutOfBoundsException("1000000", -1, 2, Character.MIN_RADIX - 1);
checkIndexOutOfBoundsException("-1", 0, 3, 10);
checkIndexOutOfBoundsException("-1", 2, 3, 10);
checkIndexOutOfBoundsException("-1", -1, 2, 10);
checkIndexOutOfBoundsException("", 10, 1, 1); checkNull(0, 1, 10);
checkIndexOutOfBoundsException("1000000", 10, 10, 4); checkNull(-1, 0, 10);
checkIndexOutOfBoundsException("1000000", Character.MAX_RADIX + 1, 10, 2); checkNull(0, 0, 10);
checkIndexOutOfBoundsException("1000000", Character.MIN_RADIX - 1, 10, 2); checkNull(0, -1, 10);
checkIndexOutOfBoundsException("1000000", Character.MAX_RADIX + 1, -1, 2);
checkIndexOutOfBoundsException("1000000", Character.MIN_RADIX - 1, -1, 2);
checkIndexOutOfBoundsException("-1", 10, 0, 3);
checkIndexOutOfBoundsException("-1", 10, 2, 3);
checkIndexOutOfBoundsException("-1", 10, -1, 2);
checkNull(10, 0, 1);
checkNull(10, -1, 0);
checkNull(10, 0, 0);
checkNull(10, 0, -1);
checkNull(-1, -1, -1); checkNull(-1, -1, -1);
} }
private static void check(String val, long expected) { private static void check(long expected, String val) {
long n = Long.parseLong(val); long n = Long.parseLong(val);
if (n != expected) if (n != expected)
throw new RuntimeException("Long.parseLong failed. String:" + throw new RuntimeException("Long.parseLong failed. String:" +
@ -127,11 +122,11 @@ public class ParsingTest {
} }
} }
private static void checkNumberFormatException(String val, int radix, int start) { private static void checkNumberFormatException(String val, int start, int end, int radix) {
long n = 0; long n = 0;
try { try {
n = Long.parseLong(val, radix, start); n = Long.parseLong(val, start, end, radix);
System.err.println("parseLong(" + val + ", " + radix + ", " + start + System.err.println("parseLong(" + val + ", " + start + ", " + end + ", " + radix +
") incorrectly returned " + n); ") incorrectly returned " + n);
throw new RuntimeException(); throw new RuntimeException();
} catch (NumberFormatException nfe) { } catch (NumberFormatException nfe) {
@ -139,23 +134,11 @@ public class ParsingTest {
} }
} }
private static void checkNumberFormatException(String val, int radix, int start, int end) { private static void checkIndexOutOfBoundsException(String val, int start, int end, int radix) {
long n = 0; long n = 0;
try { try {
n = Long.parseLong(val, radix, start, end); n = Long.parseLong(val, start, end, radix);
System.err.println("parseLong(" + val + ", " + radix + ", " + start + ", " + end + System.err.println("parseLong(" + val + ", " + start + ", " + end + ", " + radix +
") incorrectly returned " + n);
throw new RuntimeException();
} catch (NumberFormatException nfe) {
; // Expected
}
}
private static void checkIndexOutOfBoundsException(String val, int radix, int start) {
long n = 0;
try {
n = Long.parseLong(val, radix, start);
System.err.println("parseLong(" + val + ", " + radix + ", " + start +
") incorrectly returned " + n); ") incorrectly returned " + n);
throw new RuntimeException(); throw new RuntimeException();
} catch (IndexOutOfBoundsException ioob) { } catch (IndexOutOfBoundsException ioob) {
@ -163,23 +146,11 @@ public class ParsingTest {
} }
} }
private static void checkIndexOutOfBoundsException(String val, int radix, int start, int end) { private static void checkNull(int start, int end, int radix) {
long n = 0; long n = 0;
try { try {
n = Long.parseLong(val, radix, start, end); n = Long.parseLong(null, start, end, radix);
System.err.println("parseLong(" + val + ", " + radix + ", " + start + ", " + end + System.err.println("parseLong(null, " + start + ", " + end + ", " + radix +
") incorrectly returned " + n);
throw new RuntimeException();
} catch (IndexOutOfBoundsException ioob) {
; // Expected
}
}
private static void checkNull(int radix, int start, int end) {
long n = 0;
try {
n = Long.parseLong(null, 10, start, end);
System.err.println("parseLong(null, " + radix + ", " + start + ", " + end +
") incorrectly returned " + n); ") incorrectly returned " + n);
throw new RuntimeException(); throw new RuntimeException();
} catch (NullPointerException npe) { } catch (NullPointerException npe) {
@ -187,10 +158,10 @@ public class ParsingTest {
} }
} }
private static void check(String val, long expected, int start, int end) { private static void check(long expected, String val, int start, int end, int radix) {
long n = Long.parseLong(val, 10, start, end); long n = Long.parseLong(val, start, end, radix);
if (n != expected) if (n != expected)
throw new RuntimeException("Long.parseLong failed. String:" + throw new RuntimeException("Long.parseLong failed. Expexted: " + expected + " String: \"" +
val + ", start: " + start + ", end: " + end + " Result:" + n); val + "\", start: " + start + ", end: " + end + " radix: " + radix + " Result: " + n);
} }
} }

View file

@ -289,6 +289,17 @@ public class Unsigned {
"\tconverting back ''%s'' resulted in %d%n", "\tconverting back ''%s'' resulted in %d%n",
value, radix, bigString, longResult); value, radix, bigString, longResult);
} }
// test offset based parse method
longResult = Long.parseUnsignedLong("prefix" + bigString + "suffix", "prefix".length(),
"prefix".length() + bigString.length(), radix);
if (!toUnsignedBigInt(longResult).equals(value)) {
errors++;
System.err.printf("Bad roundtrip conversion of %d in base %d" +
"\tconverting back ''%s'' resulted in %d%n",
value, radix, bigString, longResult);
}
} }
} }