src/share/classes/java/lang/Long.java
Print this page
rev 9925 : 8041972: Add improved parse/format methods for Long/Integer
@@ -544,64 +544,105 @@
* the specified radix.
* @throws NumberFormatException if the string does not contain a
* parsable {@code long}.
*/
public static long parseLong(String s, int radix)
- throws NumberFormatException
- {
+ throws NumberFormatException {
+ return parseLong(s, radix, 0);
+ }
+
+ /**
+ * Extend upon Long.parseLong(String, int) by providing a start offset to enable parsing
+ * substrings without creating intermediary objects
+ * @see java.lang.Long#parseLong(String, int)
+ *
+ * @param start the start position in s to parse from, inclusive
+ */
+ static long parseLong(String s, int radix, int start)
+ throws NumberFormatException {
+ if (s == null) {
+ throw new NumberFormatException("null");
+ }
+ return parseLong(s, radix, start, s.length());
+ }
+
+ /**
+ * Extend upon Long.parseLong(String, int) by providing a start and end offset to enable parsing
+ * substrings without creating intermediary objects
+ * @see java.lang.Long#parseLong(String, int)
+ * @param start the start position in s to parse from, inclusive
+ * @param end the end position in s to parse to, exclusive
+ */
+ static long parseLong(String s, int radix, int start, int end)
+ throws NumberFormatException {
if (s == null) {
throw new NumberFormatException("null");
}
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");
}
+ if (start < 0 || start >= end) {
+ throw new NumberFormatException("start position out of bounds");
+ }
+
+ if (start == end) {
+ throw NumberFormatException.forInputString("");
+ }
+
+ if (end > s.length()) {
+ throw new NumberFormatException("end position out of bounds");
+ }
+
long result = 0;
boolean negative = false;
- int i = 0, len = s.length();
+ int i = start;
long limit = -Long.MAX_VALUE;
long multmin;
int digit;
- if (len > 0) {
- char firstChar = s.charAt(0);
+ char firstChar = s.charAt(i);
if (firstChar < '0') { // Possible leading "+" or "-"
if (firstChar == '-') {
negative = true;
limit = Long.MIN_VALUE;
- } else if (firstChar != '+')
- throw NumberFormatException.forInputString(s);
-
- if (len == 1) // Cannot have lone "+" or "-"
- throw NumberFormatException.forInputString(s);
+ } else if (firstChar != '+') {
+ throw NumberFormatException.forInputString(
+ s.substring(start, end));
+ }
+ if (end == start + 1) { // Cannot have lone "+" or "-"
+ throw NumberFormatException.forInputString(
+ s.substring(start, end));
+ }
i++;
}
multmin = limit / radix;
- while (i < len) {
+ while (i < end) {
// Accumulating negatively avoids surprises near MAX_VALUE
- digit = Character.digit(s.charAt(i++),radix);
+ digit = Character.digit(s.charAt(i++), radix);
if (digit < 0) {
- throw NumberFormatException.forInputString(s);
+ throw NumberFormatException.forInputString(
+ s.substring(start, end));
}
if (result < multmin) {
- throw NumberFormatException.forInputString(s);
+ throw NumberFormatException.forInputString(
+ s.substring(start, end));
}
result *= radix;
if (result < limit + digit) {
- throw NumberFormatException.forInputString(s);
+ throw NumberFormatException.forInputString(
+ s.substring(start, end));
}
result -= digit;
}
- } else {
- throw NumberFormatException.forInputString(s);
- }
return negative ? result : -result;
}
/**
* Parses the string argument as a signed decimal {@code long}.
@@ -677,29 +718,72 @@
public static long parseUnsignedLong(String s, int radix)
throws NumberFormatException {
if (s == null) {
throw new NumberFormatException("null");
}
+ return parseUnsignedLong(s, radix, 0);
+ }
+
+ /**
+ * Extend upon Long.parseUnsignedLong(String, int) by providing a start offset
+ * to enable parsing substrings without creating intermediary objects
+ * @see java.lang.Long#parseUnsignedLong(String, int)
+ * @param start the start position in s to parse from, inclusive
+ */
+ public static long parseUnsignedLong(String s, int radix, int start) {
+ if (s == null) {
+ throw new NumberFormatException("null");
+ }
+ return parseUnsignedLong(s, radix, start, s.length());
+ }
+
+ /**
+ * Extend upon Long.parseUnsignedLong(String, int) by providing a start offset to enable parsing
+ * substrings without creating intermediary objects
+ * @see java.lang.Long#parseUnsignedLong(String, int)
+ * @param start the start position in s to parse from, inclusive
+ * @param end the end position in s to parse to, exclusive
+ */
+ public static long parseUnsignedLong(String s, int radix, int start, int end) {
+ if (s == null) {
+ throw new NumberFormatException("null");
+ }
+
+ 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");
+ }
+
+ if (start < 0 || start > end) {
+ throw new NumberFormatException("start position out of bounds");
+ }
- int len = s.length();
- if (len > 0) {
- char firstChar = s.charAt(0);
+ if (end <= start || end > s.length()) {
+ throw new NumberFormatException("end position out of bounds");
+ }
+
+ int count = end - start;
+ char firstChar = s.charAt(start);
if (firstChar == '-') {
- throw new
- NumberFormatException(String.format("Illegal leading minus sign " +
- "on unsigned string %s.", s));
+ throw new NumberFormatException(String.format("Illegal leading minus sign " +
+ "on unsigned string %s.", s.substring(start, end)));
} 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);
+ if (count <= 12 || // Long.MAX_VALUE in Character.MAX_RADIX is 13 digits
+ (radix == 10 && count <= 18) ) { // Long.MAX_VALUE in base 10 is 19 digits
+ return parseLong(s, radix, start, end);
}
- // No need for range checks on len due to testing above.
- long first = parseLong(s.substring(0, len - 1), radix);
- int second = Character.digit(s.charAt(len - 1), radix);
+ // No need for range checks on end due to testing above.
+ long first = parseLong(s, radix, start, end - 1);
+ int second = Character.digit(s.charAt(end - 1), radix);
if (second < 0) {
- throw new NumberFormatException("Bad digit at end of " + s);
+ throw new NumberFormatException("Bad digit at end of " + s.substring(start, end));
}
long result = first * radix + second;
/*
* Test leftmost bits of multiprecision extension of first*radix
@@ -752,17 +836,14 @@
* 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));
+ "range of unsigned long.", s.substring(start, end)));
}
return result;
}
- } else {
- throw NumberFormatException.forInputString(s);
- }
}
/**
* Parses the string argument as an unsigned decimal {@code long}. The
* characters in the string must all be decimal digits, except