src/share/classes/java/lang/Integer.java

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


 510      * parseInt("-0", 10) returns 0
 511      * parseInt("-FF", 16) returns -255
 512      * parseInt("1100110", 2) returns 102
 513      * parseInt("2147483647", 10) returns 2147483647
 514      * parseInt("-2147483648", 10) returns -2147483648
 515      * parseInt("2147483648", 10) throws a NumberFormatException
 516      * parseInt("99", 8) throws a NumberFormatException
 517      * parseInt("Kona", 10) throws a NumberFormatException
 518      * parseInt("Kona", 27) returns 411787
 519      * </pre></blockquote>
 520      *
 521      * @param      s   the {@code String} containing the integer
 522      *                  representation to be parsed
 523      * @param      radix   the radix to be used while parsing {@code s}.
 524      * @return     the integer represented by the string argument in the
 525      *             specified radix.
 526      * @exception  NumberFormatException if the {@code String}
 527      *             does not contain a parsable {@code int}.
 528      */
 529     public static int parseInt(String s, int radix)
 530                 throws NumberFormatException
 531     {


























 532         /*
 533          * WARNING: This method may be invoked early during VM initialization
 534          * before IntegerCache is initialized. Care must be taken to not use
 535          * the valueOf method.
 536          */
 537 
 538         if (s == null) {
 539             throw new NumberFormatException("null");
 540         }
 541 
 542         if (radix < Character.MIN_RADIX) {
 543             throw new NumberFormatException("radix " + radix +
 544                                             " less than Character.MIN_RADIX");
 545         }
 546 
 547         if (radix > Character.MAX_RADIX) {
 548             throw new NumberFormatException("radix " + radix +
 549                                             " greater than Character.MAX_RADIX");
 550         }
 551 












 552         int result = 0;
 553         boolean negative = false;
 554         int i = 0, len = s.length();
 555         int limit = -Integer.MAX_VALUE;
 556         int multmin;
 557         int digit;
 558 
 559         if (len > 0) {
 560             char firstChar = s.charAt(0);
 561             if (firstChar < '0') { // Possible leading "+" or "-"
 562                 if (firstChar == '-') {
 563                     negative = true;
 564                     limit = Integer.MIN_VALUE;
 565                 } else if (firstChar != '+')
 566                     throw NumberFormatException.forInputString(s);


 567 
 568                 if (len == 1) // Cannot have lone "+" or "-"
 569                     throw NumberFormatException.forInputString(s);


 570                 i++;
 571             }
 572             multmin = limit / radix;
 573             while (i < len) {
 574                 // Accumulating negatively avoids surprises near MAX_VALUE
 575                 digit = Character.digit(s.charAt(i++),radix);
 576                 if (digit < 0) {
 577                     throw NumberFormatException.forInputString(s);

 578                 }
 579                 if (result < multmin) {
 580                     throw NumberFormatException.forInputString(s);

 581                 }
 582                 result *= radix;
 583                 if (result < limit + digit) {
 584                     throw NumberFormatException.forInputString(s);

 585                 }
 586                 result -= digit;
 587             }
 588         } else {
 589             throw NumberFormatException.forInputString(s);
 590         }
 591         return negative ? result : -result;
 592     }
 593 
 594     /**
 595      * Parses the string argument as a signed decimal integer. The
 596      * characters in the string must all be decimal digits, except
 597      * that the first character may be an ASCII minus sign {@code '-'}
 598      * ({@code '\u005Cu002D'}) to indicate a negative value or an
 599      * ASCII plus sign {@code '+'} ({@code '\u005Cu002B'}) to
 600      * indicate a positive value. The resulting integer value is
 601      * returned, exactly as if the argument and the radix 10 were
 602      * given as arguments to the {@link #parseInt(java.lang.String,
 603      * int)} method.
 604      *
 605      * @param s    a {@code String} containing the {@code int}
 606      *             representation to be parsed
 607      * @return     the integer value represented by the argument in decimal.
 608      * @exception  NumberFormatException  if the string does not contain a
 609      *               parsable integer.
 610      */


 640      * {@code '+'} ({@code '\u005Cu002B'}) provided that the
 641      * string is longer than length 1.
 642      *
 643      * <li>The value represented by the string is larger than the
 644      * largest unsigned {@code int}, 2<sup>32</sup>-1.
 645      *
 646      * </ul>
 647      *
 648      *
 649      * @param      s   the {@code String} containing the unsigned integer
 650      *                  representation to be parsed
 651      * @param      radix   the radix to be used while parsing {@code s}.
 652      * @return     the integer represented by the string argument in the
 653      *             specified radix.
 654      * @throws     NumberFormatException if the {@code String}
 655      *             does not contain a parsable {@code int}.
 656      * @since 1.8
 657      */
 658     public static int parseUnsignedInt(String s, int radix)
 659                 throws NumberFormatException {











 660         if (s == null)  {
 661             throw new NumberFormatException("null");
 662         }


 663 
 664         int len = s.length();












 665         if (len > 0) {
 666             char firstChar = s.charAt(0);
 667             if (firstChar == '-') {
 668                 throw new
 669                     NumberFormatException(String.format("Illegal leading minus sign " +
 670                                                        "on unsigned string %s.", s));
 671             } else {
 672                 if (len <= 5 || // Integer.MAX_VALUE in Character.MAX_RADIX is 6 digits
 673                     (radix == 10 && len <= 9) ) { // Integer.MAX_VALUE in base 10 is 10 digits
 674                     return parseInt(s, radix);
 675                 } else {
 676                     long ell = Long.parseLong(s, radix);
 677                     if ((ell & 0xffff_ffff_0000_0000L) == 0) {
 678                         return (int) ell;
 679                     } else {
 680                         throw new
 681                             NumberFormatException(String.format("String value %s exceeds " +
 682                                                                 "range of unsigned int.", s));
 683                     }
 684                 }
 685             }
 686         } else {
 687             throw NumberFormatException.forInputString(s);
 688         }
 689     }
 690 
 691     /**
 692      * Parses the string argument as an unsigned decimal integer. The
 693      * characters in the string must all be decimal digits, except
 694      * that the first character may be an an ASCII plus sign {@code
 695      * '+'} ({@code '\u005Cu002B'}). The resulting integer value
 696      * is returned, exactly as if the argument and the radix 10 were
 697      * given as arguments to the {@link
 698      * #parseUnsignedInt(java.lang.String, int)} method.
 699      *
 700      * @param s   a {@code String} containing the unsigned {@code int}
 701      *            representation to be parsed
 702      * @return    the unsigned integer value represented by the argument in decimal.
 703      * @throws    NumberFormatException  if the string does not contain a
 704      *            parsable unsigned integer.
 705      * @since 1.8
 706      */
 707     public static int parseUnsignedInt(String s) throws NumberFormatException {




 510      * parseInt("-0", 10) returns 0
 511      * parseInt("-FF", 16) returns -255
 512      * parseInt("1100110", 2) returns 102
 513      * parseInt("2147483647", 10) returns 2147483647
 514      * parseInt("-2147483648", 10) returns -2147483648
 515      * parseInt("2147483648", 10) throws a NumberFormatException
 516      * parseInt("99", 8) throws a NumberFormatException
 517      * parseInt("Kona", 10) throws a NumberFormatException
 518      * parseInt("Kona", 27) returns 411787
 519      * </pre></blockquote>
 520      *
 521      * @param      s   the {@code String} containing the integer
 522      *                  representation to be parsed
 523      * @param      radix   the radix to be used while parsing {@code s}.
 524      * @return     the integer represented by the string argument in the
 525      *             specified radix.
 526      * @exception  NumberFormatException if the {@code String}
 527      *             does not contain a parsable {@code int}.
 528      */
 529     public static int parseInt(String s, int radix)
 530                 throws NumberFormatException {
 531         return parseInt(s, radix, 0);
 532     }
 533 
 534     /**
 535      * Extend upon Integer.parseInt(String, int) by providing a start offset to enable parsing
 536      * substrings without creating intermediary objects
 537      * @see java.lang.Integer#parseInt(String, int)
 538      *
 539      * @param start the start position in s to parse from, inclusive
 540      */
 541     static int parseInt(CharSequence s, int radix, int start)
 542             throws NumberFormatException {
 543         if (s == null) {
 544             throw new NumberFormatException("null");
 545         }
 546         return parseInt(s, radix, start, s.length());
 547     }
 548 
 549     /**
 550      * Extend upon Integer.parseInt(String, int) by providing a start and end offset to enable parsing
 551      * substrings without creating intermediary objects
 552      * @see java.lang.Integer#parseInt(String, int)
 553      * @param start the start position in s to parse from, inclusive
 554      * @param end the end position in s to parse to, exclusive
 555      */
 556     static int parseInt(CharSequence s, int radix, int start, int end)
 557             throws NumberFormatException {
 558         /*
 559          * WARNING: This method may be invoked early during VM initialization
 560          * before IntegerCache is initialized. Care must be taken to not use
 561          * the valueOf method.
 562          */

 563         if (s == null) {
 564             throw new NumberFormatException("null");
 565         }
 566 
 567         if (radix < Character.MIN_RADIX) {
 568             throw new NumberFormatException("radix " + radix +
 569                                             " less than Character.MIN_RADIX");
 570         }
 571 
 572         if (radix > Character.MAX_RADIX) {
 573             throw new NumberFormatException("radix " + radix +
 574                                             " greater than Character.MAX_RADIX");
 575         }
 576 
 577         if (start < 0 || start > end) {
 578             throw new NumberFormatException("start position out of bounds");
 579         }
 580 
 581         if (start == end) {
 582             throw NumberFormatException.forInputString("");
 583         }
 584 
 585         if (end > s.length()) {
 586             throw new NumberFormatException("end position out of bounds");
 587         }
 588 
 589         int result = 0;
 590         boolean negative = false;
 591         int i = start;
 592         int limit = -Integer.MAX_VALUE;
 593         int multmin;
 594         int digit;
 595 
 596         char firstChar = s.charAt(start);

 597         if (firstChar < '0') { // Possible leading "+" or "-"
 598             if (firstChar == '-') {
 599                 negative = true;
 600                 limit = Integer.MIN_VALUE;
 601             } else if (firstChar != '+') {
 602                 throw NumberFormatException.forInputString(
 603                         s.subSequence(start, end).toString());
 604             }
 605 
 606             if (end == start + 1) { // Cannot have lone "+" or "-"
 607                 throw NumberFormatException.forInputString(
 608                         s.subSequence(start, end).toString());
 609             }
 610             i++;
 611         }
 612         multmin = limit / radix;
 613         while (i < end) {
 614             // Accumulating negatively avoids surprises near MAX_VALUE
 615             digit = Character.digit(s.charAt(i++), radix);
 616             if (digit < 0) {
 617                 throw NumberFormatException.forInputString(
 618                         s.subSequence(start, end).toString());
 619             }
 620             if (result < multmin) {
 621                 throw NumberFormatException.forInputString(
 622                         s.subSequence(start, end).toString());
 623             }
 624             result *= radix;
 625             if (result < limit + digit) {
 626                 throw NumberFormatException.forInputString(
 627                         s.subSequence(start, end).toString());
 628             }
 629             result -= digit;
 630         }



 631         return negative ? result : -result;
 632     }
 633 
 634     /**
 635      * Parses the string argument as a signed decimal integer. The
 636      * characters in the string must all be decimal digits, except
 637      * that the first character may be an ASCII minus sign {@code '-'}
 638      * ({@code '\u005Cu002D'}) to indicate a negative value or an
 639      * ASCII plus sign {@code '+'} ({@code '\u005Cu002B'}) to
 640      * indicate a positive value. The resulting integer value is
 641      * returned, exactly as if the argument and the radix 10 were
 642      * given as arguments to the {@link #parseInt(java.lang.String,
 643      * int)} method.
 644      *
 645      * @param s    a {@code String} containing the {@code int}
 646      *             representation to be parsed
 647      * @return     the integer value represented by the argument in decimal.
 648      * @exception  NumberFormatException  if the string does not contain a
 649      *               parsable integer.
 650      */


 680      * {@code '+'} ({@code '\u005Cu002B'}) provided that the
 681      * string is longer than length 1.
 682      *
 683      * <li>The value represented by the string is larger than the
 684      * largest unsigned {@code int}, 2<sup>32</sup>-1.
 685      *
 686      * </ul>
 687      *
 688      *
 689      * @param      s   the {@code String} containing the unsigned integer
 690      *                  representation to be parsed
 691      * @param      radix   the radix to be used while parsing {@code s}.
 692      * @return     the integer represented by the string argument in the
 693      *             specified radix.
 694      * @throws     NumberFormatException if the {@code String}
 695      *             does not contain a parsable {@code int}.
 696      * @since 1.8
 697      */
 698     public static int parseUnsignedInt(String s, int radix)
 699                 throws NumberFormatException {
 700         return parseUnsignedInt(s, radix, 0);
 701     }
 702 
 703     /**
 704      * Extend upon parseUnsignedInt(String, int) by providing a start offset
 705      * to enable parsing substrings without creating intermediary objects
 706      * @see java.lang.Integer#parseUnsignedInt(String, int)
 707      * @param start the start position in s to parse from, inclusive
 708      */
 709     static int parseUnsignedInt(CharSequence s, int radix, int start)
 710             throws NumberFormatException {
 711         if (s == null) {
 712             throw new NumberFormatException("null");
 713         }
 714         return parseUnsignedInt(s, radix, start, s.length());
 715     }
 716 
 717     /**
 718      * Extend upon parseUnsignedInt(String, int) by providing a start and end
 719      * offset to enable parsing substrings without creating intermediary objects
 720      * @see java.lang.Integer#parseUnsignedInt(String, int)
 721      * @param start the start position in s to parse from, inclusive
 722      * @param end the end position in s to parse to, exclusive
 723      */
 724     static int parseUnsignedInt(CharSequence s, int radix, int start, int end)
 725             throws NumberFormatException {
 726         if (s == null) {
 727             throw new NumberFormatException("null");
 728         }
 729         int len = end - start;
 730         if (len > 0) {
 731             char firstChar = s.charAt(start);
 732             if (firstChar == '-') {
 733                 throw new
 734                     NumberFormatException(String.format("Illegal leading minus sign " +
 735                                                        "on unsigned string %s.", s));
 736             } else {
 737                 if (len <= 5 || // Integer.MAX_VALUE in Character.MAX_RADIX is 6 digits
 738                     (radix == 10 && len <= 9) ) { // Integer.MAX_VALUE in base 10 is 10 digits
 739                     return parseInt(s, radix, start, end);
 740                 } else {
 741                     long ell = Long.parseLong(s, radix, start, end);
 742                     if ((ell & 0xffff_ffff_0000_0000L) == 0) {
 743                         return (int) ell;
 744                     } else {
 745                         throw new
 746                             NumberFormatException(String.format("String value %s exceeds " +
 747                                                                 "range of unsigned int.", s));
 748                     }
 749                 }
 750             }
 751         } else {
 752             throw NumberFormatException.forInputString(s.toString());
 753         }
 754     }
 755 
 756     /**
 757      * Parses the string argument as an unsigned decimal integer. The
 758      * characters in the string must all be decimal digits, except
 759      * that the first character may be an an ASCII plus sign {@code
 760      * '+'} ({@code '\u005Cu002B'}). The resulting integer value
 761      * is returned, exactly as if the argument and the radix 10 were
 762      * given as arguments to the {@link
 763      * #parseUnsignedInt(java.lang.String, int)} method.
 764      *
 765      * @param s   a {@code String} containing the unsigned {@code int}
 766      *            representation to be parsed
 767      * @return    the unsigned integer value represented by the argument in decimal.
 768      * @throws    NumberFormatException  if the string does not contain a
 769      *            parsable unsigned integer.
 770      * @since 1.8
 771      */
 772     public static int parseUnsignedInt(String s) throws NumberFormatException {