@@ -2150,10 +2150,7 @@ private void append(StringBuffer result, String string,
21502150 * #getGroupingSize()} is not adhered to
21512151 * <li> {@link #isGroupingUsed()} returns {@code false}, and the grouping
21522152 * symbol is found
2153- * <li> {@link #isParseIntegerOnly()} returns {@code true}, and the decimal
2154- * separator is found
2155- * <li> {@link #isGroupingUsed()} returns {@code true} and {@link
2156- * #isParseIntegerOnly()} returns {@code false}, and the grouping
2153+ * <li> {@link #isGroupingUsed()} returns {@code true} and the grouping
21572154 * symbol occurs after the decimal separator
21582155 * <li> Any other characters are found, that are not the expected symbols,
21592156 * and are not digits that occur within the numerical portion
@@ -2379,7 +2376,8 @@ private final boolean subparse(String text, ParsePosition parsePosition,
23792376
23802377 // position will serve as new index when success, otherwise it will
23812378 // serve as errorIndex when failure
2382- position = subparseNumber (text , position , digits , true , isExponent , status );
2379+ NumericPosition pos = subparseNumber (text , position , digits , true , isExponent , status );
2380+ position = pos .fullPos ;
23832381
23842382 // First character after the prefix was un-parseable, should
23852383 // fail regardless if lenient or strict.
@@ -2422,9 +2420,15 @@ private final boolean subparse(String text, ParsePosition parsePosition,
24222420 return false ;
24232421 }
24242422
2425- // No failures, thus increment the index by the suffix
2426- parsePosition .index = position +
2427- (gotPositive ? positiveSuffix .length () : negativeSuffix .length ());
2423+ // When parsing integer only, index should be int pos
2424+ // If intPos is 0, the entire value was integer
2425+ if (isParseIntegerOnly () && pos .intPos > 0 ) {
2426+ parsePosition .index = pos .intPos ;
2427+ } else {
2428+ // increment the index by the suffix
2429+ parsePosition .index = position +
2430+ (gotPositive ? positiveSuffix .length () : negativeSuffix .length ());
2431+ }
24282432 } else {
24292433 parsePosition .index = position ;
24302434 }
@@ -2437,6 +2441,19 @@ private final boolean subparse(String text, ParsePosition parsePosition,
24372441 return true ;
24382442 }
24392443
2444+ /**
2445+ * NumericPosition is a helper record class that stores two indices of interest.
2446+ * {@code fullPos} is either the first unparseable character or -1 in case
2447+ * of no valid number parsed. {@code intPos} reflects the position of
2448+ * a parsed decimal symbol, if one exists. When parsing with {@code isParseIntegerOnly()},
2449+ * {@code fullPos} is used to match the suffix, and reset the {@code ParsePosition}
2450+ * index to {@code intPos}.
2451+ *
2452+ * @param fullPos an index that reflects the full traversal of the numerical String
2453+ * @param intPos an index that reflects the position of a parsed decimal symbol.
2454+ */
2455+ record NumericPosition (int fullPos , int intPos ) {}
2456+
24402457 /**
24412458 * Parses a number from the given {@code text}. The text is parsed
24422459 * beginning at {@code position}, until an unparseable character is seen.
@@ -2449,14 +2466,15 @@ private final boolean subparse(String text, ParsePosition parsePosition,
24492466 * @param status upon return contains boolean status flags indicating
24502467 * whether the value is infinite and whether it is
24512468 * positive
2452- * @return returns the position of the first unparseable character or
2453- * -1 in case of no valid number parsed
2469+ * @return returns a {@code NumericPosition} that stores both a full
2470+ * traversal index, and an int only index.
24542471 */
2455- int subparseNumber (String text , int position ,
2456- DigitList digits , boolean checkExponent ,
2457- boolean isExponent , boolean [] status ) {
2472+ NumericPosition subparseNumber (String text , int position ,
2473+ DigitList digits , boolean checkExponent ,
2474+ boolean isExponent , boolean [] status ) {
24582475 // process digits or Inf, find decimal position
24592476 status [STATUS_INFINITE ] = false ;
2477+ int intIndex = 0 ;
24602478 if (!isExponent && text .regionMatches (position , symbols .getInfinity (), 0 ,
24612479 symbols .getInfinity ().length ())) {
24622480 position += symbols .getInfinity ().length ();
@@ -2516,7 +2534,7 @@ int subparseNumber(String text, int position,
25162534 if (parseStrict && isGroupingUsed () && position == startPos + groupingSize
25172535 && prevSeparatorIndex == -groupingSize && !sawDecimal
25182536 && digit >= 0 && digit <= 9 ) {
2519- return position ;
2537+ return new NumericPosition ( position , intIndex ) ;
25202538 }
25212539
25222540 if (digit == 0 ) {
@@ -2538,37 +2556,44 @@ int subparseNumber(String text, int position,
25382556 --digits .decimalAt ;
25392557 } else {
25402558 ++digitCount ;
2541- digits .append ((char )(digit + '0' ));
2559+ if (!sawDecimal || !isParseIntegerOnly ()) {
2560+ digits .append ((char )(digit + '0' ));
2561+ }
25422562 }
25432563 } else if (digit > 0 && digit <= 9 ) { // [sic] digit==0 handled above
25442564 sawDigit = true ;
25452565 ++digitCount ;
2546- digits .append ((char )(digit + '0' ));
2566+ if (!sawDecimal || !isParseIntegerOnly ()) {
2567+ digits .append ((char ) (digit + '0' ));
2568+ }
25472569
25482570 // Cancel out backup setting (see grouping handler below)
25492571 backup = -1 ;
25502572 } else if (!isExponent && ch == decimal ) {
25512573 // Check grouping size on decimal separator
25522574 if (parseStrict && isGroupingViolation (position , prevSeparatorIndex )) {
2553- return groupingViolationIndex (position , prevSeparatorIndex );
2575+ return new NumericPosition (
2576+ groupingViolationIndex (position , prevSeparatorIndex ), intIndex );
25542577 }
25552578 // If we're only parsing integers, or if we ALREADY saw the
25562579 // decimal, then don't parse this one.
2557- if (isParseIntegerOnly () || sawDecimal ) {
2580+ if (sawDecimal ) {
25582581 break ;
25592582 }
2583+ intIndex = position ;
25602584 digits .decimalAt = digitCount ; // Not digits.count!
25612585 sawDecimal = true ;
25622586 } else if (!isExponent && ch == grouping && isGroupingUsed ()) {
25632587 if (parseStrict ) {
25642588 // text should not start with grouping when strict
25652589 if (position == startPos ) {
2566- return startPos ;
2590+ return new NumericPosition ( startPos , intIndex ) ;
25672591 }
25682592 // when strict, fail if grouping occurs after decimal OR
25692593 // current group violates grouping size
25702594 if (sawDecimal || (isGroupingViolation (position , prevSeparatorIndex ))) {
2571- return groupingViolationIndex (position , prevSeparatorIndex );
2595+ return new NumericPosition (
2596+ groupingViolationIndex (position , prevSeparatorIndex ), intIndex );
25722597 }
25732598 prevSeparatorIndex = position ; // track previous
25742599 } else {
@@ -2621,7 +2646,8 @@ int subparseNumber(String text, int position,
26212646 // "1,234%" and "1,234" both end with pos = 5, since '%' breaks
26222647 // the loop before incrementing position. In both cases, check
26232648 // should be done at pos = 4
2624- return groupingViolationIndex (position - 1 , prevSeparatorIndex );
2649+ return new NumericPosition (
2650+ groupingViolationIndex (position - 1 , prevSeparatorIndex ), intIndex );
26252651 }
26262652 }
26272653
@@ -2636,8 +2662,9 @@ int subparseNumber(String text, int position,
26362662 digits .decimalAt = digitCount ; // Not digits.count!
26372663 }
26382664
2639- // Adjust for exponent, if any
2640- if (exponent != 0 ) {
2665+ // If parsing integer only, adjust exponent if it occurs
2666+ // in integer portion, otherwise ignore it
2667+ if (!sawDecimal || !isParseIntegerOnly ()) {
26412668 digits .decimalAt = shiftDecimalAt (digits .decimalAt , exponent );
26422669 }
26432670
@@ -2646,10 +2673,10 @@ int subparseNumber(String text, int position,
26462673 // parse "$" with pattern "$#0.00". (return index 0 and error
26472674 // index 1).
26482675 if (!sawDigit && digitCount == 0 ) {
2649- return - 1 ;
2676+ return new NumericPosition (- 1 , intIndex ) ;
26502677 }
26512678 }
2652- return position ;
2679+ return new NumericPosition ( position , intIndex ) ;
26532680 }
26542681
26552682 // Calculate the final decimal position based off the exponent value
@@ -2917,7 +2944,8 @@ public int getMultiplier () {
29172944 * have '{@code U+2030}'.
29182945 *
29192946 * <P>Example: with multiplier 100, 1.23 is formatted as "123", and
2920- * "123" is parsed into 1.23.
2947+ * "123" is parsed into 1.23. If {@code isParseIntegerOnly()} returns {@code true},
2948+ * "123" is parsed into 1.
29212949 *
29222950 * @param newValue the new multiplier
29232951 * @see #getMultiplier
0 commit comments