@@ -2150,10 +2150,7 @@ private void append(StringBuffer result, String string,
2150
2150
* #getGroupingSize()} is not adhered to
2151
2151
* <li> {@link #isGroupingUsed()} returns {@code false}, and the grouping
2152
2152
* 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
2157
2154
* symbol occurs after the decimal separator
2158
2155
* <li> Any other characters are found, that are not the expected symbols,
2159
2156
* and are not digits that occur within the numerical portion
@@ -2379,7 +2376,8 @@ private final boolean subparse(String text, ParsePosition parsePosition,
2379
2376
2380
2377
// position will serve as new index when success, otherwise it will
2381
2378
// 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 ;
2383
2381
2384
2382
// First character after the prefix was un-parseable, should
2385
2383
// fail regardless if lenient or strict.
@@ -2422,9 +2420,15 @@ private final boolean subparse(String text, ParsePosition parsePosition,
2422
2420
return false ;
2423
2421
}
2424
2422
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
+ }
2428
2432
} else {
2429
2433
parsePosition .index = position ;
2430
2434
}
@@ -2437,6 +2441,19 @@ private final boolean subparse(String text, ParsePosition parsePosition,
2437
2441
return true ;
2438
2442
}
2439
2443
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
+
2440
2457
/**
2441
2458
* Parses a number from the given {@code text}. The text is parsed
2442
2459
* beginning at {@code position}, until an unparseable character is seen.
@@ -2449,14 +2466,15 @@ private final boolean subparse(String text, ParsePosition parsePosition,
2449
2466
* @param status upon return contains boolean status flags indicating
2450
2467
* whether the value is infinite and whether it is
2451
2468
* 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.
2454
2471
*/
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 ) {
2458
2475
// process digits or Inf, find decimal position
2459
2476
status [STATUS_INFINITE ] = false ;
2477
+ int intIndex = 0 ;
2460
2478
if (!isExponent && text .regionMatches (position , symbols .getInfinity (), 0 ,
2461
2479
symbols .getInfinity ().length ())) {
2462
2480
position += symbols .getInfinity ().length ();
@@ -2516,7 +2534,7 @@ int subparseNumber(String text, int position,
2516
2534
if (parseStrict && isGroupingUsed () && position == startPos + groupingSize
2517
2535
&& prevSeparatorIndex == -groupingSize && !sawDecimal
2518
2536
&& digit >= 0 && digit <= 9 ) {
2519
- return position ;
2537
+ return new NumericPosition ( position , intIndex ) ;
2520
2538
}
2521
2539
2522
2540
if (digit == 0 ) {
@@ -2538,37 +2556,44 @@ int subparseNumber(String text, int position,
2538
2556
--digits .decimalAt ;
2539
2557
} else {
2540
2558
++digitCount ;
2541
- digits .append ((char )(digit + '0' ));
2559
+ if (!sawDecimal || !isParseIntegerOnly ()) {
2560
+ digits .append ((char )(digit + '0' ));
2561
+ }
2542
2562
}
2543
2563
} else if (digit > 0 && digit <= 9 ) { // [sic] digit==0 handled above
2544
2564
sawDigit = true ;
2545
2565
++digitCount ;
2546
- digits .append ((char )(digit + '0' ));
2566
+ if (!sawDecimal || !isParseIntegerOnly ()) {
2567
+ digits .append ((char ) (digit + '0' ));
2568
+ }
2547
2569
2548
2570
// Cancel out backup setting (see grouping handler below)
2549
2571
backup = -1 ;
2550
2572
} else if (!isExponent && ch == decimal ) {
2551
2573
// Check grouping size on decimal separator
2552
2574
if (parseStrict && isGroupingViolation (position , prevSeparatorIndex )) {
2553
- return groupingViolationIndex (position , prevSeparatorIndex );
2575
+ return new NumericPosition (
2576
+ groupingViolationIndex (position , prevSeparatorIndex ), intIndex );
2554
2577
}
2555
2578
// If we're only parsing integers, or if we ALREADY saw the
2556
2579
// decimal, then don't parse this one.
2557
- if (isParseIntegerOnly () || sawDecimal ) {
2580
+ if (sawDecimal ) {
2558
2581
break ;
2559
2582
}
2583
+ intIndex = position ;
2560
2584
digits .decimalAt = digitCount ; // Not digits.count!
2561
2585
sawDecimal = true ;
2562
2586
} else if (!isExponent && ch == grouping && isGroupingUsed ()) {
2563
2587
if (parseStrict ) {
2564
2588
// text should not start with grouping when strict
2565
2589
if (position == startPos ) {
2566
- return startPos ;
2590
+ return new NumericPosition ( startPos , intIndex ) ;
2567
2591
}
2568
2592
// when strict, fail if grouping occurs after decimal OR
2569
2593
// current group violates grouping size
2570
2594
if (sawDecimal || (isGroupingViolation (position , prevSeparatorIndex ))) {
2571
- return groupingViolationIndex (position , prevSeparatorIndex );
2595
+ return new NumericPosition (
2596
+ groupingViolationIndex (position , prevSeparatorIndex ), intIndex );
2572
2597
}
2573
2598
prevSeparatorIndex = position ; // track previous
2574
2599
} else {
@@ -2621,7 +2646,8 @@ int subparseNumber(String text, int position,
2621
2646
// "1,234%" and "1,234" both end with pos = 5, since '%' breaks
2622
2647
// the loop before incrementing position. In both cases, check
2623
2648
// should be done at pos = 4
2624
- return groupingViolationIndex (position - 1 , prevSeparatorIndex );
2649
+ return new NumericPosition (
2650
+ groupingViolationIndex (position - 1 , prevSeparatorIndex ), intIndex );
2625
2651
}
2626
2652
}
2627
2653
@@ -2636,8 +2662,9 @@ int subparseNumber(String text, int position,
2636
2662
digits .decimalAt = digitCount ; // Not digits.count!
2637
2663
}
2638
2664
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 ()) {
2641
2668
digits .decimalAt = shiftDecimalAt (digits .decimalAt , exponent );
2642
2669
}
2643
2670
@@ -2646,10 +2673,10 @@ int subparseNumber(String text, int position,
2646
2673
// parse "$" with pattern "$#0.00". (return index 0 and error
2647
2674
// index 1).
2648
2675
if (!sawDigit && digitCount == 0 ) {
2649
- return - 1 ;
2676
+ return new NumericPosition (- 1 , intIndex ) ;
2650
2677
}
2651
2678
}
2652
- return position ;
2679
+ return new NumericPosition ( position , intIndex ) ;
2653
2680
}
2654
2681
2655
2682
// Calculate the final decimal position based off the exponent value
@@ -2917,7 +2944,8 @@ public int getMultiplier () {
2917
2944
* have '{@code U+2030}'.
2918
2945
*
2919
2946
* <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.
2921
2949
*
2922
2950
* @param newValue the new multiplier
2923
2951
* @see #getMultiplier
0 commit comments