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

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


 529      * parseLong("0", 10) returns 0L
 530      * parseLong("473", 10) returns 473L
 531      * parseLong("+42", 10) returns 42L
 532      * parseLong("-0", 10) returns 0L
 533      * parseLong("-FF", 16) returns -255L
 534      * parseLong("1100110", 2) returns 102L
 535      * parseLong("99", 8) throws a NumberFormatException
 536      * parseLong("Hazelnut", 10) throws a NumberFormatException
 537      * parseLong("Hazelnut", 36) returns 1356099454469L
 538      * </pre></blockquote>
 539      *
 540      * @param      s       the {@code String} containing the
 541      *                     {@code long} representation to be parsed.
 542      * @param      radix   the radix to be used while parsing {@code s}.
 543      * @return     the {@code long} represented by the string argument in
 544      *             the specified radix.
 545      * @throws     NumberFormatException  if the string does not contain a
 546      *             parsable {@code long}.
 547      */
 548     public static long parseLong(String s, int radix)
 549               throws NumberFormatException
 550     {


























 551         if (s == null) {
 552             throw new NumberFormatException("null");
 553         }
 554 
 555         if (radix < Character.MIN_RADIX) {
 556             throw new NumberFormatException("radix " + radix +
 557                                             " less than Character.MIN_RADIX");
 558         }

 559         if (radix > Character.MAX_RADIX) {
 560             throw new NumberFormatException("radix " + radix +
 561                                             " greater than Character.MAX_RADIX");
 562         }
 563 












 564         long result = 0;
 565         boolean negative = false;
 566         int i = 0, len = s.length();
 567         long limit = -Long.MAX_VALUE;
 568         long multmin;
 569         int digit;
 570 
 571         if (len > 0) {
 572             char firstChar = s.charAt(0);
 573             if (firstChar < '0') { // Possible leading "+" or "-"
 574                 if (firstChar == '-') {
 575                     negative = true;
 576                     limit = Long.MIN_VALUE;
 577                 } else if (firstChar != '+')
 578                     throw NumberFormatException.forInputString(s);
 579 
 580                 if (len == 1) // Cannot have lone "+" or "-"
 581                     throw NumberFormatException.forInputString(s);



 582                 i++;
 583             }
 584             multmin = limit / radix;
 585             while (i < len) {
 586                 // Accumulating negatively avoids surprises near MAX_VALUE
 587                 digit = Character.digit(s.charAt(i++),radix);
 588                 if (digit < 0) {
 589                     throw NumberFormatException.forInputString(s);

 590                 }
 591                 if (result < multmin) {
 592                     throw NumberFormatException.forInputString(s);

 593                 }
 594                 result *= radix;
 595                 if (result < limit + digit) {
 596                     throw NumberFormatException.forInputString(s);

 597                 }
 598                 result -= digit;
 599             }
 600         } else {
 601             throw NumberFormatException.forInputString(s);
 602         }
 603         return negative ? result : -result;
 604     }
 605 
 606     /**
 607      * Parses the string argument as a signed decimal {@code long}.
 608      * The characters in the string must all be decimal digits, except
 609      * that the first character may be an ASCII minus sign {@code '-'}
 610      * ({@code \u005Cu002D'}) to indicate a negative value or an
 611      * ASCII plus sign {@code '+'} ({@code '\u005Cu002B'}) to
 612      * indicate a positive value. The resulting {@code long} value is
 613      * returned, exactly as if the argument and the radix {@code 10}
 614      * were given as arguments to the {@link
 615      * #parseLong(java.lang.String, int)} method.
 616      *
 617      * <p>Note that neither the character {@code L}
 618      * ({@code '\u005Cu004C'}) nor {@code l}
 619      * ({@code '\u005Cu006C'}) is permitted to appear at the end
 620      * of the string as a type indicator, as would be permitted in
 621      * Java programming language source code.
 622      *


 662      * <li>The value represented by the string is larger than the
 663      * largest unsigned {@code long}, 2<sup>64</sup>-1.
 664      *
 665      * </ul>
 666      *
 667      *
 668      * @param      s   the {@code String} containing the unsigned integer
 669      *                  representation to be parsed
 670      * @param      radix   the radix to be used while parsing {@code s}.
 671      * @return     the unsigned {@code long} represented by the string
 672      *             argument in the specified radix.
 673      * @throws     NumberFormatException if the {@code String}
 674      *             does not contain a parsable {@code long}.
 675      * @since 1.8
 676      */
 677     public static long parseUnsignedLong(String s, int radix)
 678                 throws NumberFormatException {
 679         if (s == null)  {
 680             throw new NumberFormatException("null");
 681         }









































 682 
 683         int len = s.length();
 684         if (len > 0) {
 685             char firstChar = s.charAt(0);



 686             if (firstChar == '-') {
 687                 throw new
 688                     NumberFormatException(String.format("Illegal leading minus sign " +
 689                                                        "on unsigned string %s.", s));
 690             } else {
 691                 if (len <= 12 || // Long.MAX_VALUE in Character.MAX_RADIX is 13 digits
 692                     (radix == 10 && len <= 18) ) { // Long.MAX_VALUE in base 10 is 19 digits
 693                     return parseLong(s, radix);
 694                 }
 695 
 696                 // No need for range checks on len due to testing above.
 697                 long first = parseLong(s.substring(0, len - 1), radix);
 698                 int second = Character.digit(s.charAt(len - 1), radix);
 699                 if (second < 0) {
 700                     throw new NumberFormatException("Bad digit at end of " + s);
 701                 }
 702                 long result = first * radix + second;
 703 
 704                 /*
 705                  * Test leftmost bits of multiprecision extension of first*radix
 706                  * for overflow. The number of bits needed is defined by
 707                  * GUARD_BIT = ceil(log2(Character.MAX_RADIX)) + 1 = 7. Then
 708                  * int guard = radix*(int)(first >>> (64 - GUARD_BIT)) and
 709                  * overflow is tested by splitting guard in the ranges
 710                  * guard < 92, 92 <= guard < 128, and 128 <= guard, where
 711                  * 92 = 128 - Character.MAX_RADIX. Note that guard cannot take
 712                  * on a value which does not include a prime factor in the legal
 713                  * radix range.
 714                  */
 715                 int guard = radix * (int) (first >>> 57);
 716                 if (guard >= 128 ||
 717                     (result >= 0 && guard >= 128 - Character.MAX_RADIX)) {
 718                     /*
 719                      * For purposes of exposition, the programmatic statements
 720                      * below should be taken to be multi-precision, i.e., not


 737                      * so that first*radix + second >= 92*2^57 + 0 > 2^63
 738                      *
 739                      * D) Condition guard < 128:
 740                      * radix*first <= (radix*left7) * 2^57 + radix*(2^57 - 1)
 741                      * so
 742                      * radix*first + second <= (radix*left7) * 2^57 + radix*(2^57 - 1) + 36
 743                      * thus
 744                      * radix*first + second < 128 * 2^57 + 36*2^57 - radix + 36
 745                      * whence
 746                      * radix*first + second < 2^64 + 2^6*2^57 = 2^64 + 2^63
 747                      *
 748                      * E) Conditions C, D, and result >= 0:
 749                      * C and D combined imply the mathematical result
 750                      * 2^63 < first*radix + second < 2^64 + 2^63. The lower
 751                      * bound is therefore negative as a signed long, but the
 752                      * upper bound is too small to overflow again after the
 753                      * signed long overflows to positive above 2^64 - 1. Hence
 754                      * result >= 0 implies overflow given C and D.
 755                      */
 756                     throw new NumberFormatException(String.format("String value %s exceeds " +
 757                                                                   "range of unsigned long.", s));
 758                 }
 759                 return result;
 760             }
 761         } else {
 762             throw NumberFormatException.forInputString(s);
 763         }
 764     }
 765 
 766     /**
 767      * Parses the string argument as an unsigned decimal {@code long}. The
 768      * characters in the string must all be decimal digits, except
 769      * that the first character may be an an ASCII plus sign {@code
 770      * '+'} ({@code '\u005Cu002B'}). The resulting integer value
 771      * is returned, exactly as if the argument and the radix 10 were
 772      * given as arguments to the {@link
 773      * #parseUnsignedLong(java.lang.String, int)} method.
 774      *
 775      * @param s   a {@code String} containing the unsigned {@code long}
 776      *            representation to be parsed
 777      * @return    the unsigned {@code long} value represented by the decimal string argument
 778      * @throws    NumberFormatException  if the string does not contain a
 779      *            parsable unsigned integer.
 780      * @since 1.8
 781      */
 782     public static long parseUnsignedLong(String s) throws NumberFormatException {




 529      * parseLong("0", 10) returns 0L
 530      * parseLong("473", 10) returns 473L
 531      * parseLong("+42", 10) returns 42L
 532      * parseLong("-0", 10) returns 0L
 533      * parseLong("-FF", 16) returns -255L
 534      * parseLong("1100110", 2) returns 102L
 535      * parseLong("99", 8) throws a NumberFormatException
 536      * parseLong("Hazelnut", 10) throws a NumberFormatException
 537      * parseLong("Hazelnut", 36) returns 1356099454469L
 538      * </pre></blockquote>
 539      *
 540      * @param      s       the {@code String} containing the
 541      *                     {@code long} representation to be parsed.
 542      * @param      radix   the radix to be used while parsing {@code s}.
 543      * @return     the {@code long} represented by the string argument in
 544      *             the specified radix.
 545      * @throws     NumberFormatException  if the string does not contain a
 546      *             parsable {@code long}.
 547      */
 548     public static long parseLong(String s, int radix)
 549               throws NumberFormatException {
 550         return parseLong(s, radix, 0);
 551     }
 552 
 553     /**
 554      * Extend upon Long.parseLong(String, int) by providing a start offset to enable parsing
 555      * substrings without creating intermediary objects
 556      * @see java.lang.Long#parseLong(String, int)
 557      *
 558      * @param start the start position in s to parse from, inclusive
 559      */
 560     static long parseLong(CharSequence s, int radix, int start)
 561             throws NumberFormatException {
 562         if (s == null) {
 563             throw new NumberFormatException("null");
 564         }
 565         return parseLong(s, radix, start, s.length());
 566     }
 567 
 568     /**
 569      * Extend upon Long.parseLong(String, int) by providing a start and end offset to enable parsing
 570      * substrings without creating intermediary objects
 571      * @see java.lang.Long#parseLong(String, int)
 572      * @param start the start position in s to parse from, inclusive
 573      * @param end the end position in s to parse to, exclusive
 574      */
 575     static long parseLong(CharSequence s, int radix, int start, int end)
 576             throws NumberFormatException {
 577         if (s == null) {
 578             throw new NumberFormatException("null");
 579         }
 580 
 581         if (radix < Character.MIN_RADIX) {
 582             throw new NumberFormatException("radix " + radix +
 583                     " less than Character.MIN_RADIX");
 584         }
 585 
 586         if (radix > Character.MAX_RADIX) {
 587             throw new NumberFormatException("radix " + radix +
 588                     " greater than Character.MAX_RADIX");
 589         }
 590 
 591         if (start < 0 || start >= end) {
 592             throw new NumberFormatException("start position out of bounds");
 593         }
 594 
 595         if (start == end) {
 596             throw NumberFormatException.forInputString("");
 597         }
 598 
 599         if (end > s.length()) {
 600             throw new NumberFormatException("end position out of bounds");
 601         }
 602 
 603         long result = 0;
 604         boolean negative = false;
 605         int i = start;
 606         long limit = -Long.MAX_VALUE;
 607         long multmin;
 608         int digit;
 609 
 610         char firstChar = s.charAt(i);

 611         if (firstChar < '0') { // Possible leading "+" or "-"
 612             if (firstChar == '-') {
 613                 negative = true;
 614                 limit = Long.MIN_VALUE;
 615             } else if (firstChar != '+') {
 616                 throw NumberFormatException.forInputString(
 617                         s.subSequence(start, end).toString());
 618             }
 619             if (end == start + 1) { // Cannot have lone "+" or "-"
 620                 throw NumberFormatException.forInputString(
 621                         s.subSequence(start, end).toString());
 622             }
 623             i++;
 624         }
 625         multmin = limit / radix;
 626         while (i < end) {
 627             // Accumulating negatively avoids surprises near MAX_VALUE
 628             digit = Character.digit(s.charAt(i++), radix);
 629             if (digit < 0) {
 630                 throw NumberFormatException.forInputString(
 631                         s.subSequence(start, end).toString());
 632             }
 633             if (result < multmin) {
 634                 throw NumberFormatException.forInputString(
 635                         s.subSequence(start, end).toString());
 636             }
 637             result *= radix;
 638             if (result < limit + digit) {
 639                 throw NumberFormatException.forInputString(
 640                         s.subSequence(start, end).toString());
 641             }
 642             result -= digit;
 643         }



 644         return negative ? result : -result;
 645     }
 646 
 647     /**
 648      * Parses the string argument as a signed decimal {@code long}.
 649      * The characters in the string must all be decimal digits, except
 650      * that the first character may be an ASCII minus sign {@code '-'}
 651      * ({@code \u005Cu002D'}) to indicate a negative value or an
 652      * ASCII plus sign {@code '+'} ({@code '\u005Cu002B'}) to
 653      * indicate a positive value. The resulting {@code long} value is
 654      * returned, exactly as if the argument and the radix {@code 10}
 655      * were given as arguments to the {@link
 656      * #parseLong(java.lang.String, int)} method.
 657      *
 658      * <p>Note that neither the character {@code L}
 659      * ({@code '\u005Cu004C'}) nor {@code l}
 660      * ({@code '\u005Cu006C'}) is permitted to appear at the end
 661      * of the string as a type indicator, as would be permitted in
 662      * Java programming language source code.
 663      *


 703      * <li>The value represented by the string is larger than the
 704      * largest unsigned {@code long}, 2<sup>64</sup>-1.
 705      *
 706      * </ul>
 707      *
 708      *
 709      * @param      s   the {@code String} containing the unsigned integer
 710      *                  representation to be parsed
 711      * @param      radix   the radix to be used while parsing {@code s}.
 712      * @return     the unsigned {@code long} represented by the string
 713      *             argument in the specified radix.
 714      * @throws     NumberFormatException if the {@code String}
 715      *             does not contain a parsable {@code long}.
 716      * @since 1.8
 717      */
 718     public static long parseUnsignedLong(String s, int radix)
 719                 throws NumberFormatException {
 720         if (s == null)  {
 721             throw new NumberFormatException("null");
 722         }
 723         return parseUnsignedLong(s, radix, 0);
 724     }
 725 
 726     /**
 727      * Extend upon Long.parseUnsignedLong(String, int) by providing a start offset
 728      * to enable parsing substrings without creating intermediary objects
 729      * @see java.lang.Long#parseUnsignedLong(String, int)
 730      * @param start the start position in s to parse from, inclusive
 731      */
 732     static long parseUnsignedLong(CharSequence s, int radix, int start) {
 733         if (s == null)  {
 734             throw new NumberFormatException("null");
 735         }
 736         return parseUnsignedLong(s, radix, start, s.length());
 737     }
 738 
 739     /**
 740      * Extend upon Long.parseUnsignedLong(String, int) by providing a start offset to enable parsing
 741      * substrings without creating intermediary objects
 742      * @see java.lang.Long#parseUnsignedLong(String, int)
 743      * @param start the start position in s to parse from, inclusive
 744      * @param end the end position in s to parse to, exclusive
 745      */
 746     static long parseUnsignedLong(CharSequence s, int radix, int start, int end) {
 747         if (s == null) {
 748             throw new NumberFormatException("null");
 749         }
 750 
 751         if (radix < Character.MIN_RADIX) {
 752             throw new NumberFormatException("radix " + radix +
 753                     " less than Character.MIN_RADIX");
 754         }
 755 
 756         if (radix > Character.MAX_RADIX) {
 757             throw new NumberFormatException("radix " + radix +
 758                     " greater than Character.MAX_RADIX");
 759         }
 760 
 761         if (start < 0 || start > end) {
 762             throw new NumberFormatException("start position out of bounds");
 763         }
 764 
 765         if (end <= start || end > s.length()) {
 766             throw new NumberFormatException("end position out of bounds");
 767         }
 768 
 769         int count = end - start;
 770         char firstChar = s.charAt(start);
 771         if (firstChar == '-') {
 772             throw new NumberFormatException(String.format("Illegal leading minus sign " +
 773                     "on unsigned string %s.", s.subSequence(start, end)));

 774         } else {
 775             if (count <= 12 || // Long.MAX_VALUE in Character.MAX_RADIX is 13 digits
 776                     (radix == 10 && count <= 18) ) { // Long.MAX_VALUE in base 10 is 19 digits
 777                 return parseLong(s, radix, start, end);
 778             }
 779 
 780             // No need for range checks on end due to testing above.
 781             long first = parseLong(s, radix, start, end - 1);
 782             int second = Character.digit(s.charAt(end - 1), radix);
 783             if (second < 0) {
 784                 throw new NumberFormatException("Bad digit at end of " + s.subSequence(start, end));
 785             }
 786             long result = first * radix + second;
 787 
 788             /*
 789              * Test leftmost bits of multiprecision extension of first*radix
 790              * for overflow. The number of bits needed is defined by
 791              * GUARD_BIT = ceil(log2(Character.MAX_RADIX)) + 1 = 7. Then
 792              * int guard = radix*(int)(first >>> (64 - GUARD_BIT)) and
 793              * overflow is tested by splitting guard in the ranges
 794              * guard < 92, 92 <= guard < 128, and 128 <= guard, where
 795              * 92 = 128 - Character.MAX_RADIX. Note that guard cannot take
 796              * on a value which does not include a prime factor in the legal
 797              * radix range.
 798              */
 799             int guard = radix * (int) (first >>> 57);
 800             if (guard >= 128 ||
 801                     (result >= 0 && guard >= 128 - Character.MAX_RADIX)) {
 802                 /*
 803                  * For purposes of exposition, the programmatic statements
 804                  * below should be taken to be multi-precision, i.e., not


 821                  * so that first*radix + second >= 92*2^57 + 0 > 2^63
 822                  *
 823                  * D) Condition guard < 128:
 824                  * radix*first <= (radix*left7) * 2^57 + radix*(2^57 - 1)
 825                  * so
 826                  * radix*first + second <= (radix*left7) * 2^57 + radix*(2^57 - 1) + 36
 827                  * thus
 828                  * radix*first + second < 128 * 2^57 + 36*2^57 - radix + 36
 829                  * whence
 830                  * radix*first + second < 2^64 + 2^6*2^57 = 2^64 + 2^63
 831                  *
 832                  * E) Conditions C, D, and result >= 0:
 833                  * C and D combined imply the mathematical result
 834                  * 2^63 < first*radix + second < 2^64 + 2^63. The lower
 835                  * bound is therefore negative as a signed long, but the
 836                  * upper bound is too small to overflow again after the
 837                  * signed long overflows to positive above 2^64 - 1. Hence
 838                  * result >= 0 implies overflow given C and D.
 839                  */
 840                 throw new NumberFormatException(String.format("String value %s exceeds " +
 841                         "range of unsigned long.", s.subSequence(start, end)));
 842             }
 843             return result;



 844         }
 845     }
 846 
 847     /**
 848      * Parses the string argument as an unsigned decimal {@code long}. The
 849      * characters in the string must all be decimal digits, except
 850      * that the first character may be an an ASCII plus sign {@code
 851      * '+'} ({@code '\u005Cu002B'}). The resulting integer value
 852      * is returned, exactly as if the argument and the radix 10 were
 853      * given as arguments to the {@link
 854      * #parseUnsignedLong(java.lang.String, int)} method.
 855      *
 856      * @param s   a {@code String} containing the unsigned {@code long}
 857      *            representation to be parsed
 858      * @return    the unsigned {@code long} value represented by the decimal string argument
 859      * @throws    NumberFormatException  if the string does not contain a
 860      *            parsable unsigned integer.
 861      * @since 1.8
 862      */
 863     public static long parseUnsignedLong(String s) throws NumberFormatException {