src/share/classes/java/lang/Long.java

Print this page
rev 9925 : 8041972: Add improved parse/format methods for Long/Integer
Contributed-by: redestad

*** 544,607 **** * 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 ! { 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"); } 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); 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); i++; } multmin = limit / radix; ! 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) { ! throw NumberFormatException.forInputString(s); } result *= radix; if (result < limit + digit) { ! throw NumberFormatException.forInputString(s); } result -= digit; } - } else { - throw NumberFormatException.forInputString(s); - } return negative ? result : -result; } /** * Parses the string argument as a signed decimal {@code long}. --- 544,648 ---- * 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 { ! 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(CharSequence 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(CharSequence 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 = start; long limit = -Long.MAX_VALUE; long multmin; int digit; ! 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.subSequence(start, end).toString()); ! } ! if (end == start + 1) { // Cannot have lone "+" or "-" ! throw NumberFormatException.forInputString( ! s.subSequence(start, end).toString()); ! } i++; } multmin = limit / radix; ! while (i < end) { // Accumulating negatively avoids surprises near MAX_VALUE ! digit = Character.digit(s.charAt(i++), radix); if (digit < 0) { ! throw NumberFormatException.forInputString( ! s.subSequence(start, end).toString()); } if (result < multmin) { ! throw NumberFormatException.forInputString( ! s.subSequence(start, end).toString()); } result *= radix; if (result < limit + digit) { ! throw NumberFormatException.forInputString( ! s.subSequence(start, end).toString()); } result -= digit; } return negative ? result : -result; } /** * Parses the string argument as a signed decimal {@code long}.
*** 677,705 **** public static long parseUnsignedLong(String s, int radix) throws NumberFormatException { if (s == null) { throw new NumberFormatException("null"); } ! 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 <= 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); } ! // 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); if (second < 0) { ! throw new NumberFormatException("Bad digit at end of " + s); } long result = first * radix + second; /* * Test leftmost bits of multiprecision extension of first*radix --- 718,789 ---- 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 + */ + static long parseUnsignedLong(CharSequence 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 + */ + static long parseUnsignedLong(CharSequence 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"); + } ! 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.subSequence(start, end))); } else { ! 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 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.subSequence(start, end)); } long result = first * radix + second; /* * Test leftmost bits of multiprecision extension of first*radix
*** 752,768 **** * 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)); } 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 --- 836,849 ---- * 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, end))); } return result; } } /** * Parses the string argument as an unsigned decimal {@code long}. The * characters in the string must all be decimal digits, except