391 * with rounding according to the context settings. |
391 * with rounding according to the context settings. |
392 * |
392 * |
393 * <p>Note that if the sequence of characters is already available |
393 * <p>Note that if the sequence of characters is already available |
394 * within a character array, using this constructor is faster than |
394 * within a character array, using this constructor is faster than |
395 * converting the {@code char} array to string and using the |
395 * converting the {@code char} array to string and using the |
396 * {@code BigDecimal(String)} constructor . |
396 * {@code BigDecimal(String)} constructor. |
397 * |
397 * |
398 * @param in {@code char} array that is the source of characters. |
398 * @param in {@code char} array that is the source of characters. |
399 * @param offset first character in the array to inspect. |
399 * @param offset first character in the array to inspect. |
400 * @param len number of characters to consider.. |
400 * @param len number of characters to consider.. |
401 * @param mc the context to use. |
401 * @param mc the context to use. |
464 if (dot) |
464 if (dot) |
465 ++scl; |
465 ++scl; |
466 } else if (c == '.') { // have dot |
466 } else if (c == '.') { // have dot |
467 // have dot |
467 // have dot |
468 if (dot) // two dots |
468 if (dot) // two dots |
469 throw new NumberFormatException(); |
469 throw new NumberFormatException("Character array" |
|
470 + " contains more than one decimal point."); |
470 dot = true; |
471 dot = true; |
471 } else if (Character.isDigit(c)) { // slow path |
472 } else if (Character.isDigit(c)) { // slow path |
472 int digit = Character.digit(c, 10); |
473 int digit = Character.digit(c, 10); |
473 if (digit == 0) { |
474 if (digit == 0) { |
474 if (prec == 0) |
475 if (prec == 0) |
486 ++scl; |
487 ++scl; |
487 } else if ((c == 'e') || (c == 'E')) { |
488 } else if ((c == 'e') || (c == 'E')) { |
488 exp = parseExp(in, offset, len); |
489 exp = parseExp(in, offset, len); |
489 // Next test is required for backwards compatibility |
490 // Next test is required for backwards compatibility |
490 if ((int) exp != exp) // overflow |
491 if ((int) exp != exp) // overflow |
491 throw new NumberFormatException(); |
492 throw new NumberFormatException("Exponent overflow."); |
492 break; // [saves a test] |
493 break; // [saves a test] |
493 } else { |
494 } else { |
494 throw new NumberFormatException(); |
495 throw new NumberFormatException("Character " + c |
|
496 + " is neither a decimal digit number, decimal point, nor" |
|
497 + " \"e\" notation exponential mark."); |
495 } |
498 } |
496 } |
499 } |
497 if (prec == 0) // no digits found |
500 if (prec == 0) // no digits found |
498 throw new NumberFormatException(); |
501 throw new NumberFormatException("No digits found."); |
499 // Adjust scale if exp is not zero. |
502 // Adjust scale if exp is not zero. |
500 if (exp != 0) { // had significant exponent |
503 if (exp != 0) { // had significant exponent |
501 scl = adjustScale(scl, exp); |
504 scl = adjustScale(scl, exp); |
502 } |
505 } |
503 rs = isneg ? -rs : rs; |
506 rs = isneg ? -rs : rs; |
539 } |
542 } |
540 // have dot |
543 // have dot |
541 if (c == '.') { |
544 if (c == '.') { |
542 // have dot |
545 // have dot |
543 if (dot) // two dots |
546 if (dot) // two dots |
544 throw new NumberFormatException(); |
547 throw new NumberFormatException("Character array" |
|
548 + " contains more than one decimal point."); |
545 dot = true; |
549 dot = true; |
546 continue; |
550 continue; |
547 } |
551 } |
548 // exponent expected |
552 // exponent expected |
549 if ((c != 'e') && (c != 'E')) |
553 if ((c != 'e') && (c != 'E')) |
550 throw new NumberFormatException(); |
554 throw new NumberFormatException("Character array" |
|
555 + " is missing \"e\" notation exponential mark."); |
551 exp = parseExp(in, offset, len); |
556 exp = parseExp(in, offset, len); |
552 // Next test is required for backwards compatibility |
557 // Next test is required for backwards compatibility |
553 if ((int) exp != exp) // overflow |
558 if ((int) exp != exp) // overflow |
554 throw new NumberFormatException(); |
559 throw new NumberFormatException("Exponent overflow."); |
555 break; // [saves a test] |
560 break; // [saves a test] |
556 } |
561 } |
557 // here when no characters left |
562 // here when no characters left |
558 if (prec == 0) // no digits found |
563 if (prec == 0) // no digits found |
559 throw new NumberFormatException(); |
564 throw new NumberFormatException("No digits found."); |
560 // Adjust scale if exp is not zero. |
565 // Adjust scale if exp is not zero. |
561 if (exp != 0) { // had significant exponent |
566 if (exp != 0) { // had significant exponent |
562 scl = adjustScale(scl, exp); |
567 scl = adjustScale(scl, exp); |
563 } |
568 } |
564 // Remove leading zeros from precision (digits count) |
569 // Remove leading zeros from precision (digits count) |
590 } |
595 } |
591 rb = null; |
596 rb = null; |
592 } |
597 } |
593 } |
598 } |
594 } |
599 } |
595 } catch (ArrayIndexOutOfBoundsException e) { |
600 } catch (ArrayIndexOutOfBoundsException | NegativeArraySizeException e) { |
596 throw new NumberFormatException(); |
601 NumberFormatException nfe = new NumberFormatException(); |
597 } catch (NegativeArraySizeException e) { |
602 nfe.initCause(e); |
598 throw new NumberFormatException(); |
603 throw nfe; |
599 } |
604 } |
600 this.scale = scl; |
605 this.scale = scl; |
601 this.precision = prec; |
606 this.precision = prec; |
602 this.intCompact = rs; |
607 this.intCompact = rs; |
603 this.intVal = rb; |
608 this.intVal = rb; |
625 offset++; |
630 offset++; |
626 c = in[offset]; |
631 c = in[offset]; |
627 len--; |
632 len--; |
628 } |
633 } |
629 if (len <= 0) // no exponent digits |
634 if (len <= 0) // no exponent digits |
630 throw new NumberFormatException(); |
635 throw new NumberFormatException("No exponent digits."); |
631 // skip leading zeros in the exponent |
636 // skip leading zeros in the exponent |
632 while (len > 10 && (c=='0' || (Character.digit(c, 10) == 0))) { |
637 while (len > 10 && (c=='0' || (Character.digit(c, 10) == 0))) { |
633 offset++; |
638 offset++; |
634 c = in[offset]; |
639 c = in[offset]; |
635 len--; |
640 len--; |
636 } |
641 } |
637 if (len > 10) // too many nonzero exponent digits |
642 if (len > 10) // too many nonzero exponent digits |
638 throw new NumberFormatException(); |
643 throw new NumberFormatException("Too many nonzero exponent digits."); |
639 // c now holds first digit of exponent |
644 // c now holds first digit of exponent |
640 for (;; len--) { |
645 for (;; len--) { |
641 int v; |
646 int v; |
642 if (c >= '0' && c <= '9') { |
647 if (c >= '0' && c <= '9') { |
643 v = c - '0'; |
648 v = c - '0'; |
644 } else { |
649 } else { |
645 v = Character.digit(c, 10); |
650 v = Character.digit(c, 10); |
646 if (v < 0) // not a digit |
651 if (v < 0) // not a digit |
647 throw new NumberFormatException(); |
652 throw new NumberFormatException("Not a digit."); |
648 } |
653 } |
649 exp = exp * 10 + v; |
654 exp = exp * 10 + v; |
650 if (len == 1) |
655 if (len == 1) |
651 break; // that was final character |
656 break; // that was final character |
652 offset++; |
657 offset++; |