mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 06:45:07 +02:00
8317515: Unify the code of the parse*() families of methods in j.l.Integer and j.l.Long
Reviewed-by: redestad
This commit is contained in:
parent
a64794b1ed
commit
b62e774e6a
2 changed files with 296 additions and 367 deletions
|
@ -38,6 +38,7 @@ import java.lang.invoke.MethodHandles;
|
|||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import static java.lang.Character.digit;
|
||||
import static java.lang.String.COMPACT_STRINGS;
|
||||
import static java.lang.String.LATIN1;
|
||||
import static java.lang.String.UTF16;
|
||||
|
@ -538,8 +539,7 @@ public final class Integer extends Number
|
|||
* does not contain a parsable {@code int}.
|
||||
*/
|
||||
public static int parseInt(String s, int radix)
|
||||
throws NumberFormatException
|
||||
{
|
||||
throws NumberFormatException {
|
||||
/*
|
||||
* WARNING: This method may be invoked early during VM initialization
|
||||
* before IntegerCache is initialized. Care must be taken to not use
|
||||
|
@ -551,52 +551,41 @@ public final class Integer extends Number
|
|||
}
|
||||
|
||||
if (radix < Character.MIN_RADIX) {
|
||||
throw new NumberFormatException("radix " + radix +
|
||||
" less than Character.MIN_RADIX");
|
||||
throw new NumberFormatException(String.format(
|
||||
"radix %s less than Character.MIN_RADIX", radix));
|
||||
}
|
||||
|
||||
if (radix > Character.MAX_RADIX) {
|
||||
throw new NumberFormatException("radix " + radix +
|
||||
" greater than Character.MAX_RADIX");
|
||||
throw new NumberFormatException(String.format(
|
||||
"radix %s greater than Character.MAX_RADIX", radix));
|
||||
}
|
||||
|
||||
boolean negative = false;
|
||||
int i = 0, len = s.length();
|
||||
int limit = -Integer.MAX_VALUE;
|
||||
|
||||
if (len > 0) {
|
||||
char firstChar = s.charAt(0);
|
||||
if (firstChar < '0') { // Possible leading "+" or "-"
|
||||
if (firstChar == '-') {
|
||||
negative = true;
|
||||
limit = Integer.MIN_VALUE;
|
||||
} else if (firstChar != '+') {
|
||||
throw NumberFormatException.forInputString(s, radix);
|
||||
}
|
||||
|
||||
if (len == 1) { // Cannot have lone "+" or "-"
|
||||
throw NumberFormatException.forInputString(s, radix);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
int len = s.length();
|
||||
if (len == 0) {
|
||||
throw new NumberFormatException("");
|
||||
}
|
||||
int digit = ~0xFF;
|
||||
int i = 0;
|
||||
char firstChar = s.charAt(i++);
|
||||
if (firstChar != '-' && firstChar != '+') {
|
||||
digit = digit(firstChar, radix);
|
||||
}
|
||||
if (digit >= 0 || digit == ~0xFF && len > 1) {
|
||||
int limit = firstChar != '-' ? MIN_VALUE + 1 : MIN_VALUE;
|
||||
int multmin = limit / radix;
|
||||
int result = 0;
|
||||
while (i < len) {
|
||||
// Accumulating negatively avoids surprises near MAX_VALUE
|
||||
int digit = Character.digit(s.charAt(i++), radix);
|
||||
if (digit < 0 || result < multmin) {
|
||||
throw NumberFormatException.forInputString(s, radix);
|
||||
}
|
||||
result *= radix;
|
||||
if (result < limit + digit) {
|
||||
throw NumberFormatException.forInputString(s, radix);
|
||||
}
|
||||
result -= digit;
|
||||
int result = -(digit & 0xFF);
|
||||
boolean inRange = true;
|
||||
/* Accumulating negatively avoids surprises near MAX_VALUE */
|
||||
while (i < len && (digit = digit(s.charAt(i++), radix)) >= 0
|
||||
&& (inRange = result > multmin
|
||||
|| result == multmin && digit <= radix * multmin - limit)) {
|
||||
result = radix * result - digit;
|
||||
}
|
||||
if (inRange && i == len && digit >= 0) {
|
||||
return firstChar != '-' ? -result : result;
|
||||
}
|
||||
return negative ? result : -result;
|
||||
} else {
|
||||
throw NumberFormatException.forInputString(s, radix);
|
||||
}
|
||||
throw NumberFormatException.forInputString(s, radix);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -632,55 +621,47 @@ public final class Integer extends Number
|
|||
Objects.checkFromToIndex(beginIndex, endIndex, s.length());
|
||||
|
||||
if (radix < Character.MIN_RADIX) {
|
||||
throw new NumberFormatException("radix " + radix +
|
||||
" less than Character.MIN_RADIX");
|
||||
throw new NumberFormatException(String.format(
|
||||
"radix %s less than Character.MIN_RADIX", radix));
|
||||
}
|
||||
|
||||
if (radix > Character.MAX_RADIX) {
|
||||
throw new NumberFormatException("radix " + radix +
|
||||
" greater than Character.MAX_RADIX");
|
||||
throw new NumberFormatException(String.format(
|
||||
"radix %s greater than Character.MAX_RADIX", radix));
|
||||
}
|
||||
|
||||
boolean negative = false;
|
||||
/*
|
||||
* While s can be concurrently modified, it is ensured that each
|
||||
* of its characters is read at most once, from lower to higher indices.
|
||||
* This is obtained by reading them using the pattern s.charAt(i++),
|
||||
* and by not updating i anywhere else.
|
||||
*/
|
||||
if (beginIndex == endIndex) {
|
||||
throw new NumberFormatException("");
|
||||
}
|
||||
int digit = ~0xFF;
|
||||
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);
|
||||
}
|
||||
i++;
|
||||
result -= digit;
|
||||
}
|
||||
return negative ? result : -result;
|
||||
} else {
|
||||
throw NumberFormatException.forInputString("", radix);
|
||||
char firstChar = s.charAt(i++);
|
||||
if (firstChar != '-' && firstChar != '+') {
|
||||
digit = digit(firstChar, radix);
|
||||
}
|
||||
if (digit >= 0 || digit == ~0xFF && endIndex - beginIndex > 1) {
|
||||
int limit = firstChar != '-' ? MIN_VALUE + 1 : MIN_VALUE;
|
||||
int multmin = limit / radix;
|
||||
int result = -(digit & 0xFF);
|
||||
boolean inRange = true;
|
||||
/* Accumulating negatively avoids surprises near MAX_VALUE */
|
||||
while (i < endIndex && (digit = digit(s.charAt(i++), radix)) >= 0
|
||||
&& (inRange = result > multmin
|
||||
|| result == multmin && digit <= radix * multmin - limit)) {
|
||||
result = radix * result - digit;
|
||||
}
|
||||
if (inRange && i == endIndex && digit >= 0) {
|
||||
return firstChar != '-' ? -result : result;
|
||||
}
|
||||
}
|
||||
throw NumberFormatException.forCharSequence(s, beginIndex,
|
||||
endIndex, i - (digit < -1 ? 0 : 1));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -701,7 +682,7 @@ public final class Integer extends Number
|
|||
* parsable integer.
|
||||
*/
|
||||
public static int parseInt(String s) throws NumberFormatException {
|
||||
return parseInt(s,10);
|
||||
return parseInt(s, 10);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -753,31 +734,48 @@ public final class Integer extends Number
|
|||
throw new NumberFormatException("Cannot parse null string");
|
||||
}
|
||||
|
||||
if (radix < Character.MIN_RADIX) {
|
||||
throw new NumberFormatException(String.format(
|
||||
"radix %s less than Character.MIN_RADIX", radix));
|
||||
}
|
||||
|
||||
if (radix > Character.MAX_RADIX) {
|
||||
throw new NumberFormatException(String.format(
|
||||
"radix %s greater than Character.MAX_RADIX", radix));
|
||||
}
|
||||
|
||||
int len = s.length();
|
||||
if (len > 0) {
|
||||
char firstChar = s.charAt(0);
|
||||
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);
|
||||
} else {
|
||||
long ell = Long.parseLong(s, radix);
|
||||
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 {
|
||||
if (len == 0) {
|
||||
throw NumberFormatException.forInputString(s, radix);
|
||||
}
|
||||
int i = 0;
|
||||
char firstChar = s.charAt(i++);
|
||||
if (firstChar == '-') {
|
||||
throw new NumberFormatException(String.format(
|
||||
"Illegal leading minus sign on unsigned string %s.", s));
|
||||
}
|
||||
int digit = ~0xFF;
|
||||
if (firstChar != '+') {
|
||||
digit = digit(firstChar, radix);
|
||||
}
|
||||
if (digit >= 0 || digit == ~0xFF && len > 1) {
|
||||
int multmax = divideUnsigned(-1, radix); // -1 is max unsigned int
|
||||
int result = digit & 0xFF;
|
||||
boolean inRange = true;
|
||||
while (i < len && (digit = digit(s.charAt(i++), radix)) >= 0
|
||||
&& (inRange = compareUnsigned(result, multmax) < 0
|
||||
|| result == multmax && digit < -radix * multmax)) {
|
||||
result = radix * result + digit;
|
||||
}
|
||||
if (inRange && i == len && digit >= 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
if (digit < 0) {
|
||||
throw NumberFormatException.forInputString(s, radix);
|
||||
}
|
||||
throw new NumberFormatException(String.format(
|
||||
"String value %s exceeds range of unsigned int.", s));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -812,32 +810,54 @@ public final class Integer extends Number
|
|||
Objects.requireNonNull(s);
|
||||
Objects.checkFromToIndex(beginIndex, endIndex, s.length());
|
||||
|
||||
int start = beginIndex, len = endIndex - beginIndex;
|
||||
if (radix < Character.MIN_RADIX) {
|
||||
throw new NumberFormatException(String.format(
|
||||
"radix %s less than Character.MIN_RADIX", radix));
|
||||
}
|
||||
|
||||
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, start, start + len, radix);
|
||||
} else {
|
||||
long ell = Long.parseLong(s, start, start + len, radix);
|
||||
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 {
|
||||
if (radix > Character.MAX_RADIX) {
|
||||
throw new NumberFormatException(String.format(
|
||||
"radix %s greater than Character.MAX_RADIX", radix));
|
||||
}
|
||||
|
||||
/*
|
||||
* While s can be concurrently modified, it is ensured that each
|
||||
* of its characters is read at most once, from lower to higher indices.
|
||||
* This is obtained by reading them using the pattern s.charAt(i++),
|
||||
* and by not updating i anywhere else.
|
||||
*/
|
||||
if (beginIndex == endIndex) {
|
||||
throw new NumberFormatException("");
|
||||
}
|
||||
int i = beginIndex;
|
||||
char firstChar = s.charAt(i++);
|
||||
if (firstChar == '-') {
|
||||
throw new NumberFormatException(
|
||||
"Illegal leading minus sign on unsigned string " + s + ".");
|
||||
}
|
||||
int digit = ~0xFF;
|
||||
if (firstChar != '+') {
|
||||
digit = digit(firstChar, radix);
|
||||
}
|
||||
if (digit >= 0 || digit == ~0xFF && endIndex - beginIndex > 1) {
|
||||
int multmax = divideUnsigned(-1, radix); // -1 is max unsigned int
|
||||
int result = digit & 0xFF;
|
||||
boolean inRange = true;
|
||||
while (i < endIndex && (digit = digit(s.charAt(i++), radix)) >= 0
|
||||
&& (inRange = compareUnsigned(result, multmax) < 0
|
||||
|| result == multmax && digit < -radix * multmax)) {
|
||||
result = radix * result + digit;
|
||||
}
|
||||
if (inRange && i == endIndex && digit >= 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
if (digit < 0) {
|
||||
throw NumberFormatException.forCharSequence(s, beginIndex,
|
||||
endIndex, i - (digit < -1 ? 0 : 1));
|
||||
}
|
||||
throw new NumberFormatException(String.format(
|
||||
"String value %s exceeds range of unsigned int.", s));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue