# HG changeset patch # User claes.redestad@oracle.com # Date 1409920617 -7200 # Fri Sep 05 14:36:57 2014 +0200 # Node ID 30f35bd4cd3b85f6df34ccb0c30dcf1f312119f5 # Parent 5c44885297cd3d01a1bb43d112a4cf161837862b 8055251: Re-examine Integer.parseInt and Long.parseLong methods diff --git a/src/java.base/share/classes/java/lang/Integer.java b/src/java.base/share/classes/java/lang/Integer.java --- a/src/java.base/share/classes/java/lang/Integer.java +++ b/src/java.base/share/classes/java/lang/Integer.java @@ -595,37 +595,6 @@ /** * 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 - */ - 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 - * 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 @@ -633,9 +602,9 @@ * * @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. + * @param radix the radix to be used while parsing {@code s}. * @return the signed {@code int} represented by the subsequence in * the specified radix. * @throws NullPointerException if {@code s} is null. @@ -650,7 +619,7 @@ * {@link java.lang.Character#MAX_RADIX}. * @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 { s = Objects.requireNonNull(s); @@ -690,7 +659,7 @@ int result = 0; while (i < endIndex) { // 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) { throw NumberFormatException.forCharSequence(s, beginIndex, endIndex, i); @@ -700,6 +669,7 @@ throw NumberFormatException.forCharSequence(s, beginIndex, endIndex, i); } + i++; result -= digit; } return negative ? result : -result; @@ -808,37 +778,6 @@ /** * 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 - */ - 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 - * 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 @@ -846,9 +785,9 @@ * * @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. + * @param radix the radix to be used while parsing {@code s}. * @return the unsigned {@code int} represented by the subsequence in * the specified radix. * @throws NullPointerException if {@code s} is null. @@ -863,7 +802,7 @@ * {@link java.lang.Character#MAX_RADIX}. * @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 { s = Objects.requireNonNull(s); @@ -881,9 +820,9 @@ } 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); + return parseInt(s, start, start + len, radix); } 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) { return (int) ell; } else { diff --git a/src/java.base/share/classes/java/lang/Long.java b/src/java.base/share/classes/java/lang/Long.java --- a/src/java.base/share/classes/java/lang/Long.java +++ b/src/java.base/share/classes/java/lang/Long.java @@ -606,37 +606,6 @@ /** * 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 - */ - 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 * the specified {@code radix}, beginning at the specified * {@code beginIndex} and extending to {@code endIndex - 1}. * @@ -645,9 +614,9 @@ * * @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. + * @param radix the radix to be used while parsing {@code s}. * @return the signed {@code long} represented by the subsequence in * the specified radix. * @throws NullPointerException if {@code s} is null. @@ -662,7 +631,7 @@ * {@link java.lang.Character#MAX_RADIX}. * @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 { s = Objects.requireNonNull(s); @@ -702,7 +671,7 @@ long result = 0; while (i < endIndex) { // 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) { throw NumberFormatException.forCharSequence(s, beginIndex, endIndex, i); @@ -712,6 +681,7 @@ throw NumberFormatException.forCharSequence(s, beginIndex, endIndex, i); } + i++; result -= digit; } return negative ? result : -result; @@ -811,7 +781,7 @@ } // 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); if (second < 0) { throw new NumberFormatException("Bad digit at end of " + s); @@ -883,37 +853,6 @@ /** * 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 - */ - 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 - * 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 @@ -921,9 +860,9 @@ * * @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. + * @param radix the radix to be used while parsing {@code s}. * @return the unsigned {@code long} represented by the subsequence in * the specified radix. * @throws NullPointerException if {@code s} is null. @@ -938,7 +877,7 @@ * {@link java.lang.Character#MAX_RADIX}. * @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 { s = Objects.requireNonNull(s); @@ -955,11 +894,11 @@ } 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); + return parseLong(s, start, start + len, radix); } // 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); if (second < 0) { throw new NumberFormatException("Bad digit at end of " + diff --git a/src/java.base/share/classes/java/time/Duration.java b/src/java.base/share/classes/java/time/Duration.java --- a/src/java.base/share/classes/java/time/Duration.java +++ b/src/java.base/share/classes/java/time/Duration.java @@ -424,7 +424,7 @@ return 0; } try { - long val = Long.parseLong(text, 10, start, end); + long val = Long.parseLong(text, start, end, 10); return Math.multiplyExact(val, multiplier); } catch (NumberFormatException | ArithmeticException ex) { throw (DateTimeParseException) new DateTimeParseException("Text cannot be parsed to a Duration: " + errorText, text, 0).initCause(ex); @@ -437,7 +437,7 @@ return 0; } 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 // were trailing zeros diff --git a/src/java.base/share/classes/java/time/Period.java b/src/java.base/share/classes/java/time/Period.java --- a/src/java.base/share/classes/java/time/Period.java +++ b/src/java.base/share/classes/java/time/Period.java @@ -358,7 +358,7 @@ if (start < 0 || end < 0) { return 0; } - int val = Integer.parseInt(text, 10, start, end); + int val = Integer.parseInt(text, start, end, 10); try { return Math.multiplyExact(val, negate); } catch (ArithmeticException ex) { diff --git a/src/java.base/share/classes/java/util/UUID.java b/src/java.base/share/classes/java/util/UUID.java --- a/src/java.base/share/classes/java/util/UUID.java +++ b/src/java.base/share/classes/java/util/UUID.java @@ -194,7 +194,8 @@ * */ public static UUID fromString(String name) { - if (name.length() > 36) { + int len = name.length(); + if (len > 36) { throw new IllegalArgumentException("UUID string too large"); } @@ -214,15 +215,14 @@ 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 |= Long.parseLong(name, 16, dash1 + 1, dash2) & 0xffffL; + mostSigBits |= Long.parseLong(name, dash1 + 1, dash2, 16) & 0xffffL; mostSigBits <<= 16; - mostSigBits |= Long.parseLong(name, 16, dash2 + 1, dash3) & 0xffffL; - - long leastSigBits = Long.parseLong(name, 16, dash3 + 1, dash4) & 0xffffL; + mostSigBits |= Long.parseLong(name, dash2 + 1, dash3, 16) & 0xffffL; + long leastSigBits = Long.parseLong(name, dash3 + 1, dash4, 16) & 0xffffL; leastSigBits <<= 48; - leastSigBits |= Long.parseLong(name, 16, dash4 + 1) & 0xffffffffffffL; + leastSigBits |= Long.parseLong(name, dash4 + 1, len, 16) & 0xffffffffffffL; return new UUID(mostSigBits, leastSigBits); } diff --git a/test/java/lang/Integer/ParsingTest.java b/test/java/lang/Integer/ParsingTest.java --- a/test/java/lang/Integer/ParsingTest.java +++ b/test/java/lang/Integer/ParsingTest.java @@ -23,24 +23,22 @@ /* * @test - * @bug 5017980 6576055 8041972 + * @bug 5017980 6576055 8041972 8055251 * @summary Test parsing methods * @author Joseph D. Darcy */ -import java.lang.IllegalArgumentException; import java.lang.IndexOutOfBoundsException; import java.lang.NullPointerException; 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: * * 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(CharSequence s, int beginIndex, int endIndex, int radix) * public static int parseInt(String s, int radix) * public static int parseInt(String s) * public static Integer valueOf(String s, int radix) @@ -55,20 +53,17 @@ public class ParsingTest { 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("+00000", 0); - check("-00000", 0); + check(0, "+0"); + check(0, "-0"); + check(0, "+00000"); + check(0, "-00000"); - check("+00000", 0, 0, 6); - check("-00000", 0, 0, 6); - - check("0", 0); - check("1", 1); - check("9", 9); + check(0, "0"); + check(1, "1"); + check(9, "9"); checkFailure(""); checkFailure("\u0000"); @@ -85,41 +80,37 @@ checkFailure("-+6"); checkFailure("*100"); - check("test-00000", 0, 4, 10); - check("test-12345", -12345, 4, 10); - check("xx12345yy", 12345, 2, 7); + // check offset based methods + check(0, "+00000", 0, 6, 10); + 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("100", 10, 3); - checkNumberFormatException("+1000000", 10, 8); - checkNumberFormatException("-1000000", 10, 8); + checkNumberFormatException("", 0, 0, 10); + checkNumberFormatException("+-6", 0, 3, 10); + checkNumberFormatException("1000000", 7, 7, 10); + checkNumberFormatException("1000000", 0, 2, Character.MAX_RADIX + 1); + checkNumberFormatException("1000000", 0, 2, Character.MIN_RADIX - 1); - 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, 4, 10); + checkIndexOutOfBoundsException("1000000", -1, 2, Character.MAX_RADIX + 1); + checkIndexOutOfBoundsException("1000000", -1, 2, Character.MIN_RADIX - 1); + checkIndexOutOfBoundsException("1000000", 10, 2, Character.MAX_RADIX + 1); + checkIndexOutOfBoundsException("1000000", 10, 2, Character.MIN_RADIX - 1); + checkIndexOutOfBoundsException("-1", 0, 3, 10); + checkIndexOutOfBoundsException("-1", 2, 3, 10); + checkIndexOutOfBoundsException("-1", -1, 2, 10); - 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(0, 1, 10); + checkNull(-1, 0, 10); + checkNull(0, 0, 10); + checkNull(0, -1, 10); 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); if (n != expected) throw new RuntimeException("Integer.parseInt failed. String:" + @@ -137,11 +128,11 @@ } } - 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; try { - n = Integer.parseInt(val, radix, start); - System.err.println("parseInt(" + val + ", " + radix + ", " + start + + n = Integer.parseInt(val, start, end, radix); + System.err.println("parseInt(" + val + ", " + start + ", " + end + ", " + radix + ") incorrectly returned " + n); throw new RuntimeException(); } catch (NumberFormatException nfe) { @@ -149,23 +140,11 @@ } } - 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; try { - n = Integer.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 = Integer.parseInt(val, radix, start); - System.err.println("parseInt(" + val + ", " + radix + ", " + start + + n = Integer.parseInt(val, start, end, radix); + System.err.println("parseInt(" + val + ", " + start + ", " + end + ", " + radix + ") incorrectly returned " + n); throw new RuntimeException(); } catch (IndexOutOfBoundsException ioob) { @@ -173,23 +152,11 @@ } } - 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; try { - n = Integer.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 = Integer.parseInt(null, 10, start, end); - System.err.println("parseInt(null, " + radix + ", " + start + ", " + end + + n = Integer.parseInt(null, start, end, radix); + System.err.println("parseInt(null, " + start + ", " + end + ", " + radix + ") incorrectly returned " + n); throw new RuntimeException(); } catch (NullPointerException npe) { @@ -197,10 +164,10 @@ } } - private static void check(String val, int expected, int start, int end) { - int n = Integer.parseInt(val, 10, start, end); + private static void check(int expected, String val, int start, int end, int radix) { + int n = Integer.parseInt(val, start, end, radix); if (n != expected) - throw new RuntimeException("Integer.parsedInt failed. String:" + - val + ", start: " + start + ", end: " + end + " Result:" + n); + throw new RuntimeException("Integer.parsedInt failed. Expected: " + expected + " String: \"" + + val + "\", start: " + start + ", end: " + end + ", radix: " + radix + " Result:" + n); } } diff --git a/test/java/lang/Integer/Unsigned.java b/test/java/lang/Integer/Unsigned.java --- a/test/java/lang/Integer/Unsigned.java +++ b/test/java/lang/Integer/Unsigned.java @@ -303,6 +303,17 @@ "\tconverting back ''%s'' resulted in %d%n", 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); + } } } diff --git a/test/java/lang/Long/ParsingTest.java b/test/java/lang/Long/ParsingTest.java --- a/test/java/lang/Long/ParsingTest.java +++ b/test/java/lang/Long/ParsingTest.java @@ -23,19 +23,18 @@ /* * @test - * @bug 5017980 6576055 8041972 + * @bug 5017980 6576055 8041972 8055251 * @summary Test parsing methods * @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: * * 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) @@ -49,17 +48,17 @@ public class ParsingTest { public static void main(String... argv) { - check("+100", +100L); - check("-100", -100L); + check(+100L, "+100"); + check(-100L, "-100"); - check("+0", 0L); - check("-0", 0L); - check("+00000", 0L); - check("-00000", 0L); + check(0L, "+0"); + check(0L, "-0"); + check(0L, "+00000"); + check(0L, "-00000"); - check("0", 0L); - check("1", 1L); - check("9", 9L); + check(0L, "0"); + check(1L, "1"); + check(9L, "9"); checkFailure(""); checkFailure("\u0000"); @@ -76,40 +75,36 @@ 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); + check(0L, "test-00000", 4, 10, 10); + check(-12345L, "test-12345", 4, 10, 10); + check(12345L, "xx12345yy", 2, 7, 10); + check(123456789012345L, "xx123456789012345yy", 2, 17, 10); + check(15L, "xxFyy", 2, 3, 16); - checkNumberFormatException("100", 10, 3); - checkNumberFormatException("", 10, 0); - checkNumberFormatException("+1000000", 10, 8); - checkNumberFormatException("-1000000", 10, 8); + checkNumberFormatException("", 0, 0, 10); + checkNumberFormatException("+-6", 0, 3, 10); + checkNumberFormatException("1000000", 7, 7, 10); + checkNumberFormatException("1000000", 0, 2, Character.MAX_RADIX + 1); + checkNumberFormatException("1000000", 0, 2, Character.MIN_RADIX - 1); - 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("", 1, 1, 10); + checkIndexOutOfBoundsException("1000000", 10, 4, 10); + checkIndexOutOfBoundsException("1000000", 10, 2, Character.MAX_RADIX + 1); + checkIndexOutOfBoundsException("1000000", 10, 2, Character.MIN_RADIX - 1); + 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); - 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(0, 1, 10); + checkNull(-1, 0, 10); + checkNull(0, 0, 10); + checkNull(0, -1, 10); 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); if (n != expected) throw new RuntimeException("Long.parseLong failed. String:" + @@ -127,11 +122,11 @@ } } - 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; try { - n = Long.parseLong(val, radix, start); - System.err.println("parseLong(" + val + ", " + radix + ", " + start + + n = Long.parseLong(val, start, end, radix); + System.err.println("parseLong(" + val + ", " + start + ", " + end + ", " + radix + ") incorrectly returned " + n); throw new RuntimeException(); } catch (NumberFormatException nfe) { @@ -139,23 +134,11 @@ } } - 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; try { - n = Long.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 = Long.parseLong(val, radix, start); - System.err.println("parseLong(" + val + ", " + radix + ", " + start + + n = Long.parseLong(val, start, end, radix); + System.err.println("parseLong(" + val + ", " + start + ", " + end + ", " + radix + ") incorrectly returned " + n); throw new RuntimeException(); } catch (IndexOutOfBoundsException ioob) { @@ -163,23 +146,11 @@ } } - 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; try { - n = Long.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 = Long.parseLong(null, 10, start, end); - System.err.println("parseLong(null, " + radix + ", " + start + ", " + end + + n = Long.parseLong(null, start, end, radix); + System.err.println("parseLong(null, " + start + ", " + end + ", " + radix + ") incorrectly returned " + n); throw new RuntimeException(); } catch (NullPointerException npe) { @@ -187,10 +158,10 @@ } } - private static void check(String val, long expected, int start, int end) { - long n = Long.parseLong(val, 10, start, end); + private static void check(long expected, String val, int start, int end, int radix) { + long n = Long.parseLong(val, start, end, radix); if (n != expected) - throw new RuntimeException("Long.parseLong failed. String:" + - val + ", start: " + start + ", end: " + end + " Result:" + n); + throw new RuntimeException("Long.parseLong failed. Expexted: " + expected + " String: \"" + + val + "\", start: " + start + ", end: " + end + " radix: " + radix + " Result: " + n); } } diff --git a/test/java/lang/Long/Unsigned.java b/test/java/lang/Long/Unsigned.java --- a/test/java/lang/Long/Unsigned.java +++ b/test/java/lang/Long/Unsigned.java @@ -289,6 +289,17 @@ "\tconverting back ''%s'' resulted in %d%n", 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); + } } }