--- old/src/share/classes/java/lang/Integer.java 2014-08-11 17:56:56.518040436 +0200 +++ new/src/share/classes/java/lang/Integer.java 2014-08-11 17:56:56.382040439 +0200 @@ -26,6 +26,7 @@ package java.lang; import java.lang.annotation.Native; +import java.util.Objects; /** * The {@code Integer} class wraps a value of the primitive type @@ -555,12 +556,9 @@ " greater than Character.MAX_RADIX"); } - int result = 0; boolean negative = false; int i = 0, len = s.length(); int limit = -Integer.MAX_VALUE; - int multmin; - int digit; if (len > 0) { char firstChar = s.charAt(0); @@ -568,21 +566,21 @@ if (firstChar == '-') { negative = true; limit = Integer.MIN_VALUE; - } else if (firstChar != '+') + } else if (firstChar != '+') { throw NumberFormatException.forInputString(s); + } - if (len == 1) // Cannot have lone "+" or "-" + if (len == 1) { // Cannot have lone "+" or "-" throw NumberFormatException.forInputString(s); + } i++; } - multmin = limit / radix; + int multmin = limit / radix; + int result = 0; while (i < len) { // Accumulating negatively avoids surprises near MAX_VALUE - digit = Character.digit(s.charAt(i++),radix); - if (digit < 0) { - throw NumberFormatException.forInputString(s); - } - if (result < multmin) { + int digit = Character.digit(s.charAt(i++), radix); + if (digit < 0 || result < multmin) { throw NumberFormatException.forInputString(s); } result *= radix; @@ -591,10 +589,126 @@ } result -= digit; } + return negative ? result : -result; } else { throw NumberFormatException.forInputString(s); } - return negative ? result : -result; + } + + /** + * 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. + * + *
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 + */ + 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 + * specified {@code radix}, beginning at the specified {@code beginIndex} + * and extending to {@code endIndex - 1}. + * + *
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. + * @param endIndex the ending index, exclusive. + * @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 endIndex} or if {@code endIndex} 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 + */ + static int parseInt(CharSequence s, int radix, int beginIndex, int endIndex) + throws NumberFormatException { + s = Objects.requireNonNull(s); + + if (beginIndex < 0 || beginIndex > endIndex || endIndex > s.length()) { + throw new IndexOutOfBoundsException(); + } + if (radix < Character.MIN_RADIX) { + throw new NumberFormatException("radix " + radix + + " less than Character.MIN_RADIX"); + } + if (radix > Character.MAX_RADIX) { + throw new NumberFormatException("radix " + radix + + " greater than Character.MAX_RADIX"); + } + + boolean negative = false; + int i = beginIndex; + int limit = -Integer.MAX_VALUE; + + if (i < endIndex) { + char firstChar = s.charAt(i); + if (firstChar < '0') { // Possible leading "+" or "-" + if (firstChar == '-') { + negative = true; + limit = Integer.MIN_VALUE; + } else if (firstChar != '+') { + throw NumberFormatException.forCharSequence(s, beginIndex, + endIndex, i); + } + i++; + if (i == endIndex) { // Cannot have lone "+" or "-" + throw NumberFormatException.forCharSequence(s, beginIndex, + endIndex, i); + } + } + int multmin = limit / radix; + int result = 0; + while (i < endIndex) { + // Accumulating negatively avoids surprises near MAX_VALUE + int digit = Character.digit(s.charAt(i++), radix); + if (digit < 0 || result < multmin) { + throw NumberFormatException.forCharSequence(s, beginIndex, + endIndex, i); + } + result *= radix; + if (result < limit + digit) { + throw NumberFormatException.forCharSequence(s, beginIndex, + endIndex, i); + } + result -= digit; + } + return negative ? result : -result; + } else { + throw NumberFormatException.forInputString(""); + } } /** @@ -694,6 +808,99 @@ } } + /** + * 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. + * + *
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 + */ + 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 + * the specified {@code radix}, beginning at the specified + * {@code beginIndex} and extending to {@code endIndex - 1}. + * + *
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. + * @param endIndex the ending index, exclusive. + * @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 endIndex} or if {@code endIndex} 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 + */ + static int parseUnsignedInt(CharSequence s, int radix, int beginIndex, int endIndex) + throws NumberFormatException { + s = Objects.requireNonNull(s); + + if (beginIndex < 0 || beginIndex > endIndex || endIndex > s.length()) { + throw new IndexOutOfBoundsException(); + } + int start = beginIndex, len = endIndex - beginIndex; + + if (len > 0) { + char firstChar = s.charAt(start); + if (firstChar == '-') { + throw new + NumberFormatException(String.format("Illegal leading minus sign " + + "on unsigned string %s.", s)); + } else { + 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 + return parseInt(s, radix, start, start + len); + } else { + long ell = Long.parseLong(s, radix, start, start + len); + if ((ell & 0xffff_ffff_0000_0000L) == 0) { + return (int) ell; + } else { + throw new + NumberFormatException(String.format("String value %s exceeds " + + "range of unsigned int.", s)); + } + } + } + } else { + throw new NumberFormatException(""); + } + } + /** * Parses the string argument as an unsigned decimal integer. The * characters in the string must all be decimal digits, except --- old/src/share/classes/java/lang/Long.java 2014-08-11 17:56:57.190040421 +0200 +++ new/src/share/classes/java/lang/Long.java 2014-08-11 17:56:57.062040424 +0200 @@ -27,6 +27,7 @@ import java.lang.annotation.Native; import java.math.*; +import java.util.Objects; /** @@ -564,12 +565,9 @@ " greater than Character.MAX_RADIX"); } - long result = 0; boolean negative = false; int i = 0, len = s.length(); long limit = -Long.MAX_VALUE; - long multmin; - int digit; if (len > 0) { char firstChar = s.charAt(0); @@ -577,21 +575,21 @@ if (firstChar == '-') { negative = true; limit = Long.MIN_VALUE; - } else if (firstChar != '+') + } else if (firstChar != '+') { throw NumberFormatException.forInputString(s); + } - if (len == 1) // Cannot have lone "+" or "-" + if (len == 1) { // Cannot have lone "+" or "-" throw NumberFormatException.forInputString(s); + } i++; } - multmin = limit / radix; + long multmin = limit / radix; + long result = 0; while (i < len) { // Accumulating negatively avoids surprises near MAX_VALUE - digit = Character.digit(s.charAt(i++),radix); - if (digit < 0) { - throw NumberFormatException.forInputString(s); - } - if (result < multmin) { + int digit = Character.digit(s.charAt(i++),radix); + if (digit < 0 || result < multmin) { throw NumberFormatException.forInputString(s); } result *= radix; @@ -600,10 +598,126 @@ } result -= digit; } + return negative ? result : -result; } else { throw NumberFormatException.forInputString(s); } - return negative ? result : -result; + } + + /** + * 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. + * + *
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 + */ + 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 + * the specified {@code radix}, beginning at the specified + * {@code beginIndex} and extending to {@code endIndex - 1}. + * + *
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. + * @param endIndex the ending index, exclusive. + * @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 endIndex} or if {@code endIndex} 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 + */ + static long parseLong(CharSequence s, int radix, int beginIndex, int endIndex) + throws NumberFormatException { + s = Objects.requireNonNull(s); + + if (beginIndex < 0 || beginIndex > endIndex || endIndex > s.length()) { + throw new IndexOutOfBoundsException(); + } + if (radix < Character.MIN_RADIX) { + throw new NumberFormatException("radix " + radix + + " less than Character.MIN_RADIX"); + } + if (radix > Character.MAX_RADIX) { + throw new NumberFormatException("radix " + radix + + " greater than Character.MAX_RADIX"); + } + + boolean negative = false; + int i = beginIndex; + long limit = -Long.MAX_VALUE; + + if (i < endIndex) { + char firstChar = s.charAt(i); + if (firstChar < '0') { // Possible leading "+" or "-" + if (firstChar == '-') { + negative = true; + limit = Long.MIN_VALUE; + } else if (firstChar != '+') { + throw NumberFormatException.forCharSequence(s, beginIndex, + endIndex, i); + } + i++; + } + if (i >= endIndex) { // Cannot have lone "+", "-" or "" + throw NumberFormatException.forCharSequence(s, beginIndex, + endIndex, i); + } + long multmin = limit / radix; + long result = 0; + while (i < endIndex) { + // Accumulating negatively avoids surprises near MAX_VALUE + int digit = Character.digit(s.charAt(i++), radix); + if (digit < 0 || result < multmin) { + throw NumberFormatException.forCharSequence(s, beginIndex, + endIndex, i); + } + result *= radix; + if (result < limit + digit) { + throw NumberFormatException.forCharSequence(s, beginIndex, + endIndex, i); + } + result -= digit; + } + return negative ? result : -result; + } else { + throw new NumberFormatException(""); + } } /** @@ -697,7 +811,7 @@ } // No need for range checks on len due to testing above. - long first = parseLong(s.substring(0, len - 1), radix); + long first = parseLong(s, radix, 0, len - 1); int second = Character.digit(s.charAt(len - 1), radix); if (second < 0) { throw new NumberFormatException("Bad digit at end of " + s); @@ -729,6 +843,155 @@ } } + /** + * 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. + * + *
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 + */ + 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 + * the specified {@code radix}, beginning at the specified + * {@code beginIndex} and extending to {@code endIndex - 1}. + * + *
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.
+ * @param endIndex the ending index, exclusive.
+ * @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 endIndex} or if {@code endIndex} 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
+ */
+ static long parseUnsignedLong(CharSequence s, int radix, int beginIndex, int endIndex)
+ throws NumberFormatException {
+ s = Objects.requireNonNull(s);
+
+ if (beginIndex < 0 || beginIndex > endIndex || endIndex > s.length()) {
+ throw new IndexOutOfBoundsException();
+ }
+ int start = beginIndex, len = endIndex - beginIndex;
+
+ if (len > 0) {
+ char firstChar = s.charAt(start);
+ if (firstChar == '-') {
+ throw new NumberFormatException(String.format("Illegal leading minus sign " +
+ "on unsigned string %s.", s.subSequence(start, start + len)));
+ } else {
+ 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
+ return parseLong(s, radix, start, start + len);
+ }
+
+ // No need for range checks on end due to testing above.
+ long first = parseLong(s, radix, start, start + len - 1);
+ int second = Character.digit(s.charAt(start + len - 1), radix);
+ if (second < 0) {
+ throw new NumberFormatException("Bad digit at end of " +
+ s.subSequence(start, start + len));
+ }
+ long result = first * radix + second;
+
+ /*
+ * Test leftmost bits of multiprecision extension of first*radix
+ * for overflow. The number of bits needed is defined by
+ * GUARD_BIT = ceil(log2(Character.MAX_RADIX)) + 1 = 7. Then
+ * int guard = radix*(int)(first >>> (64 - GUARD_BIT)) and
+ * overflow is tested by splitting guard in the ranges
+ * guard < 92, 92 <= guard < 128, and 128 <= guard, where
+ * 92 = 128 - Character.MAX_RADIX. Note that guard cannot take
+ * on a value which does not include a prime factor in the legal
+ * radix range.
+ */
+ int guard = radix * (int) (first >>> 57);
+ if (guard >= 128 ||
+ (result >= 0 && guard >= 128 - Character.MAX_RADIX)) {
+ /*
+ * For purposes of exposition, the programmatic statements
+ * below should be taken to be multi-precision, i.e., not
+ * subject to overflow.
+ *
+ * A) Condition guard >= 128:
+ * If guard >= 128 then first*radix >= 2^7 * 2^57 = 2^64
+ * hence always overflow.
+ *
+ * B) Condition guard < 92:
+ * Define left7 = first >>> 57.
+ * Given first = (left7 * 2^57) + (first & (2^57 - 1)) then
+ * result <= (radix*left7)*2^57 + radix*(2^57 - 1) + second.
+ * Thus if radix*left7 < 92, radix <= 36, and second < 36,
+ * then result < 92*2^57 + 36*(2^57 - 1) + 36 = 2^64 hence
+ * never overflow.
+ *
+ * C) Condition 92 <= guard < 128:
+ * first*radix + second >= radix*left7*2^57 + second
+ * so that first*radix + second >= 92*2^57 + 0 > 2^63
+ *
+ * D) Condition guard < 128:
+ * radix*first <= (radix*left7) * 2^57 + radix*(2^57 - 1)
+ * so
+ * radix*first + second <= (radix*left7) * 2^57 + radix*(2^57 - 1) + 36
+ * thus
+ * radix*first + second < 128 * 2^57 + 36*2^57 - radix + 36
+ * whence
+ * radix*first + second < 2^64 + 2^6*2^57 = 2^64 + 2^63
+ *
+ * E) Conditions C, D, and result >= 0:
+ * C and D combined imply the mathematical result
+ * 2^63 < first*radix + second < 2^64 + 2^63. The lower
+ * bound is therefore negative as a signed long, but the
+ * upper bound is too small to overflow again after the
+ * signed long overflows to positive above 2^64 - 1. Hence
+ * result >= 0 implies overflow given C and D.
+ */
+ throw new NumberFormatException(String.format("String value %s exceeds " +
+ "range of unsigned long.", s.subSequence(start, start + len)));
+ }
+ return result;
+ }
+ } else {
+ throw NumberFormatException.forInputString("");
+ }
+ }
+
/**
* Parses the string argument as an unsigned decimal {@code long}. The
* characters in the string must all be decimal digits, except
--- old/src/share/classes/java/lang/NumberFormatException.java 2014-08-11 17:56:57.866040406 +0200
+++ new/src/share/classes/java/lang/NumberFormatException.java 2014-08-11 17:56:57.734040409 +0200
@@ -56,7 +56,7 @@
}
/**
- * Factory method for making a NumberFormatException
+ * Factory method for making a {@code NumberFormatException}
* given the specified input which caused the error.
*
* @param s the input causing the error
@@ -64,4 +64,20 @@
static NumberFormatException forInputString(String s) {
return new NumberFormatException("For input string: \"" + s + "\"");
}
+
+ /**
+ * Factory method for making a {@code NumberFormatException}
+ * given the specified input which caused the error.
+ *
+ * @param s the input causing the error
+ * @param beginIndex the beginning index, inclusive.
+ * @param endIndex the ending index, exclusive.
+ * @param errorIndex the index of the first error in s
+ */
+ static NumberFormatException forCharSequence(CharSequence s,
+ int beginIndex, int endIndex, int errorIndex) {
+ return new NumberFormatException("Error at index "
+ + (errorIndex - beginIndex) + " in: \""
+ + s.subSequence(beginIndex, endIndex) + "\"");
+ }
}
--- old/src/share/classes/java/lang/System.java 2014-08-11 17:56:58.794040386 +0200
+++ new/src/share/classes/java/lang/System.java 2014-08-11 17:56:58.666040389 +0200
@@ -1272,6 +1272,30 @@
public void formatUnsignedInt(int val, int shift, char[] buf, int offset, int len) {
Integer.formatUnsignedInt(val, shift, buf, offset, len);
}
+ public int parseInt(CharSequence s, int radix, int beginIndex) {
+ return Integer.parseInt(s, radix, beginIndex);
+ }
+ public int parseInt(CharSequence s, int radix, int beginIndex, int endIndex) {
+ return Integer.parseInt(s, radix, beginIndex, endIndex);
+ }
+ public int parseUnsignedInt(CharSequence s, int radix, int beginIndex) {
+ return Integer.parseUnsignedInt(s, radix, beginIndex);
+ }
+ public int parseUnsignedInt(CharSequence s, int radix, int beginIndex, int endIndex) {
+ return Integer.parseUnsignedInt(s, radix, beginIndex, endIndex);
+ }
+ public long parseLong(CharSequence s, int radix, int beginIndex) {
+ return Long.parseLong(s, radix, beginIndex);
+ }
+ public long parseLong(CharSequence s, int radix, int beginIndex, int endIndex) {
+ return Long.parseLong(s, radix, beginIndex, endIndex);
+ }
+ public long parseUnsignedLong(CharSequence s, int radix, int beginIndex) {
+ return Long.parseUnsignedLong(s, radix, beginIndex);
+ }
+ public long parseUnsignedLong(CharSequence s, int radix, int beginIndex, int endIndex) {
+ return Long.parseUnsignedLong(s, radix, beginIndex, endIndex);
+ }
});
}
}
--- old/src/share/classes/sun/misc/JavaLangAccess.java 2014-08-11 17:56:59.450040372 +0200
+++ new/src/share/classes/sun/misc/JavaLangAccess.java 2014-08-11 17:56:59.318040375 +0200
@@ -142,4 +142,45 @@
* Invokes Integer.formatUnsignedInt(long val, int shift, char[] buf, int offset, int len)
*/
void formatUnsignedInt(int val, int shift, char[] buf, int offset, int len);
+
+ /**
+ * Invokes Integer.parseInt(CharSequence s, int radix, int beginIndex)
+ */
+ int parseInt(CharSequence s, int radix, int beginIndex);
+
+ /**
+ * Invokes Integer.parseInt(CharSequence s, int radix, int beginIndex, int endIndex)
+ */
+ int parseInt(CharSequence s, int radix, int beginIndex, int endIndex);
+
+ /**
+ * Invokes Integer.parseUnsignedInt(CharSequence s, int radix, int beginIndex)
+ */
+ int parseUnsignedInt(CharSequence s, int radix, int beginIndex);
+
+ /**
+ * Invokes Integer.parseUnsignedInt(CharSequence s, int radix, int beginIndex, int endIndex)
+ */
+ int parseUnsignedInt(CharSequence s, int radix, int beginIndex, int endIndex);
+
+ /**
+ * Invokes Long.parseLong(CharSequence s, int radix, int beginIndex)
+ */
+ long parseLong(CharSequence s, int radix, int beginIndex);
+
+ /**
+ * Invokes Long.parseLong(CharSequence s, int radix, int beginIndex, int endIndex)
+ */
+ long parseLong(CharSequence s, int radix, int beginIndex, int endIndex);
+
+ /**
+ * Invokes Long.parseUnsignedLong(CharSequence s, int radix, int beginIndex)
+ */
+ long parseUnsignedLong(CharSequence s, int radix, int beginIndex);
+
+ /**
+ * Invokes Long.parseUnsignedLong(CharSequence s, int radix, int beginIndex, int endIndex)
+ */
+ long parseUnsignedLong(CharSequence s, int radix, int beginIndex, int endIndex);
+
}
--- old/test/java/lang/Integer/ParsingTest.java 2014-08-11 17:57:00.086040358 +0200
+++ new/test/java/lang/Integer/ParsingTest.java 2014-08-11 17:56:59.950040361 +0200
@@ -23,29 +23,42 @@
/*
* @test
- * @bug 5017980 6576055
+ * @bug 5017980 6576055 8041972
* @summary Test parsing methods
* @author Joseph D. Darcy
*/
+import java.lang.IllegalArgumentException;
+import java.lang.IndexOutOfBoundsException;
+import java.lang.NullPointerException;
+import java.lang.RuntimeException;
+
+import sun.misc.SharedSecrets;
+import sun.misc.JavaLangAccess;
/**
- * There are six methods in java.lang.Integer which transform strings
+ * There are eight methods in java.lang.Integer which transform strings
* into an int or Integer value:
*
* public Integer(String s)
* 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 radix, int beginIndex)
* public static int parseInt(String s, int radix)
* public static int parseInt(String s)
* public static Integer valueOf(String s, int radix)
* public static Integer valueOf(String s)
*
* Besides decode, all the methods and constructor call down into
- * parseInt(String, int) to do the actual work. Therefore, the
- * behavior of parseInt(String, int) will be tested here.
+ * parseInt(CharSequence, int, int, int) to do the actual work. Therefore, the
+ * behavior of parseInt(CharSequence, int, int, int) will be tested here.
+ *
*/
public class ParsingTest {
+
+ private static final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
+
public static void main(String... argv) {
check("+100", +100);
check("-100", -100);
@@ -55,10 +68,14 @@
check("+00000", 0);
check("-00000", 0);
+ check("+00000", 0, 0, 6);
+ check("-00000", 0, 0, 6);
+
check("0", 0);
check("1", 1);
check("9", 9);
+ checkFailure("");
checkFailure("\u0000");
checkFailure("\u002f");
checkFailure("+");
@@ -72,12 +89,45 @@
checkFailure("+-6");
checkFailure("-+6");
checkFailure("*100");
+
+ check("test-00000", 0, 4, 10);
+ check("test-12345", -12345, 4, 10);
+ check("xx12345yy", 12345, 2, 7);
+
+ checkNumberFormatException("", 10, 0);
+ checkNumberFormatException("100", 10, 3);
+ checkNumberFormatException("+1000000", 10, 8);
+ checkNumberFormatException("-1000000", 10, 8);
+
+ checkNumberFormatException("", 10, 0, 0);
+ checkNumberFormatException("+-6", 10, 0, 3);
+ checkNumberFormatException("1000000", 10, 7);
+ checkNumberFormatException("1000000", 10, 7, 7);
+ checkNumberFormatException("1000000", Character.MAX_RADIX + 1, 0, 2);
+ checkNumberFormatException("1000000", Character.MIN_RADIX - 1, 0, 2);
+
+ checkIndexOutOfBoundsException("1000000", 10, 8);
+ checkIndexOutOfBoundsException("1000000", 10, -1);
+ checkIndexOutOfBoundsException("1000000", 10, 10, 4);
+ checkIndexOutOfBoundsException("1000000", Character.MAX_RADIX + 1, -1, 2);
+ 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);
}
private static void check(String val, int expected) {
int n = Integer.parseInt(val);
if (n != expected)
- throw new RuntimeException("Integer.parsedInt failed. String:" +
+ throw new RuntimeException("Integer.parseInt failed. String:" +
val + " Result:" + n);
}
@@ -91,4 +141,71 @@
; // Expected
}
}
+
+ private static void checkNumberFormatException(String val, int radix, int start) {
+ int n = 0;
+ try {
+ n = jla.parseInt(val, radix, start);
+ System.err.println("parseInt(" + val + ", " + radix + ", " + start +
+ ") incorrectly returned " + n);
+ throw new RuntimeException();
+ } catch (NumberFormatException nfe) {
+ ; // Expected
+ }
+ }
+
+ private static void checkNumberFormatException(String val, int radix, int start, int end) {
+ int n = 0;
+ try {
+ n = jla.parseInt(val, radix, start, end);
+ System.err.println("parseInt(" + val + ", " + radix + ", " + start + ", " + end +
+ ") 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 = jla.parseInt(val, radix, start);
+ System.err.println("parseInt(" + val + ", " + radix + ", " + start +
+ ") incorrectly returned " + n);
+ throw new RuntimeException();
+ } catch (IndexOutOfBoundsException ioob) {
+ ; // Expected
+ }
+ }
+
+ private static void checkIndexOutOfBoundsException(String val, int radix, int start, int end) {
+ int n = 0;
+ try {
+ n = jla.parseInt(val, radix, start, end);
+ System.err.println("parseInt(" + val + ", " + radix + ", " + start + ", " + end +
+ ") 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 = jla.parseInt(null, 10, start, end);
+ System.err.println("parseInt(null, " + radix + ", " + start + ", " + end +
+ ") incorrectly returned " + n);
+ throw new RuntimeException();
+ } catch (NullPointerException npe) {
+ ; // Expected
+ }
+ }
+
+ private static void check(String val, int expected, int start, int end) {
+ int n = jla.parseInt(val, 10, start, end);
+ if (n != expected)
+ throw new RuntimeException("Integer.parsedInt failed. String:" +
+ val + ", start: " + start + ", end: " + end + " Result:" + n);
+ }
}
--- old/test/java/lang/Long/ParsingTest.java 2014-08-11 17:57:00.738040344 +0200
+++ new/test/java/lang/Long/ParsingTest.java 2014-08-11 17:57:00.598040347 +0200
@@ -23,29 +23,36 @@
/*
* @test
- * @bug 5017980 6576055
+ * @bug 5017980 6576055 8041972
* @summary Test parsing methods
* @author Joseph D. Darcy
*/
+import sun.misc.SharedSecrets;
+import sun.misc.JavaLangAccess;
/**
- * There are six methods in java.lang.Long which transform strings
+ * There are eight methods in java.lang.Long which transform strings
* into a long or Long value:
*
* public Long(String s)
* 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)
* public static long parseLong(String s, int radix)
* public static long parseLong(String s)
* public static Long valueOf(String s, int radix)
* public static Long valueOf(String s)
*
* Besides decode, all the methods and constructor call down into
- * parseLong(String, int) to do the actual work. Therefore, the
- * behavior of parseLong(String, int) will be tested here.
+ * parseLong(CharSequence, int, int, int) to do the actual work. Therefore, the
+ * behavior of parseLong(CharSequence, int, int, int) will be tested here.
*/
public class ParsingTest {
+
+ private static final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
+
public static void main(String... argv) {
check("+100", +100L);
check("-100", -100L);
@@ -59,6 +66,7 @@
check("1", 1L);
check("9", 9L);
+ checkFailure("");
checkFailure("\u0000");
checkFailure("\u002f");
checkFailure("+");
@@ -72,12 +80,44 @@
checkFailure("+-6");
checkFailure("-+6");
checkFailure("*100");
+
+ check("test-00000", 0L, 4, 10);
+ check("test-12345", -12345L, 4, 10);
+ check("xx12345yy", 12345L, 2, 7);
+ check("xx123456789012345yy", 123456789012345L, 2, 17);
+
+ checkNumberFormatException("100", 10, 3);
+ checkNumberFormatException("", 10, 0);
+ checkNumberFormatException("+1000000", 10, 8);
+ checkNumberFormatException("-1000000", 10, 8);
+
+ checkNumberFormatException("", 10, 0, 0);
+ checkNumberFormatException("+-6", 10, 0, 3);
+ checkNumberFormatException("1000000", 10, 7, 7);
+ checkNumberFormatException("1000000", Character.MAX_RADIX + 1, 0, 2);
+ checkNumberFormatException("1000000", Character.MIN_RADIX - 1, 0, 2);
+
+ checkIndexOutOfBoundsException("", 10, 1, 1);
+ checkIndexOutOfBoundsException("1000000", 10, 10, 4);
+ checkIndexOutOfBoundsException("1000000", Character.MAX_RADIX + 1, 10, 2);
+ checkIndexOutOfBoundsException("1000000", Character.MIN_RADIX - 1, 10, 2);
+ 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);
}
private static void check(String val, long expected) {
long n = Long.parseLong(val);
if (n != expected)
- throw new RuntimeException("Long.parsedLong failed. String:" +
+ throw new RuntimeException("Long.parseLong failed. String:" +
val + " Result:" + n);
}
@@ -91,4 +131,71 @@
; // Expected
}
}
+
+ private static void checkNumberFormatException(String val, int radix, int start) {
+ long n = 0;
+ try {
+ n = jla.parseLong(val, radix, start);
+ System.err.println("parseLong(" + val + ", " + radix + ", " + start +
+ ") incorrectly returned " + n);
+ throw new RuntimeException();
+ } catch (NumberFormatException nfe) {
+ ; // Expected
+ }
+ }
+
+ private static void checkNumberFormatException(String val, int radix, int start, int end) {
+ long n = 0;
+ try {
+ n = jla.parseLong(val, radix, start, end);
+ System.err.println("parseLong(" + val + ", " + radix + ", " + start + ", " + end +
+ ") 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 = jla.parseLong(val, radix, start);
+ System.err.println("parseLong(" + val + ", " + radix + ", " + start +
+ ") incorrectly returned " + n);
+ throw new RuntimeException();
+ } catch (IndexOutOfBoundsException ioob) {
+ ; // Expected
+ }
+ }
+
+ private static void checkIndexOutOfBoundsException(String val, int radix, int start, int end) {
+ long n = 0;
+ try {
+ n = jla.parseLong(val, radix, start, end);
+ System.err.println("parseLong(" + val + ", " + radix + ", " + start + ", " + end +
+ ") 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 = jla.parseLong(null, 10, start, end);
+ System.err.println("parseLong(null, " + radix + ", " + start + ", " + end +
+ ") incorrectly returned " + n);
+ throw new RuntimeException();
+ } catch (NullPointerException npe) {
+ ; // Expected
+ }
+ }
+
+ private static void check(String val, long expected, int start, int end) {
+ long n = jla.parseLong(val, 10, start, end);
+ if (n != expected)
+ throw new RuntimeException("Long.parseLong failed. String:" +
+ val + ", start: " + start + ", end: " + end + " Result:" + n);
+ }
}