LEFT | RIGHT |
(no file at all) | |
| 1 // © 2017 and later: Unicode, Inc. and others. |
| 2 // License & terms of use: http://www.unicode.org/copyright.html#License |
| 3 package com.ibm.icu.impl.number.parse; |
| 4 |
| 5 import java.math.BigDecimal; |
| 6 import java.util.Comparator; |
| 7 |
| 8 import com.ibm.icu.impl.number.DecimalQuantity_DualStorageBCD; |
| 9 |
| 10 /** |
| 11 * @author sffc |
| 12 * |
| 13 */ |
| 14 public class ParsedNumber { |
| 15 |
| 16 public DecimalQuantity_DualStorageBCD quantity; |
| 17 |
| 18 /** |
| 19 * The number of chars accepted during parsing. This is NOT necessarily the
same as the StringSegment offset; "weak" |
| 20 * chars, like whitespace, change the offset, but the charsConsumed is not t
ouched until a "strong" char is |
| 21 * encountered. |
| 22 */ |
| 23 public int charsConsumed; |
| 24 |
| 25 /** |
| 26 * Boolean flags (see constants below). |
| 27 */ |
| 28 public int flags; |
| 29 |
| 30 /** |
| 31 * The prefix string that got consumed. |
| 32 */ |
| 33 public String prefix; |
| 34 |
| 35 /** |
| 36 * The suffix string that got consumed. |
| 37 */ |
| 38 public String suffix; |
| 39 |
| 40 /** |
| 41 * The currency that got consumed. |
| 42 */ |
| 43 public String currencyCode; |
| 44 |
| 45 public static final int FLAG_NEGATIVE = 0x0001; |
| 46 public static final int FLAG_PERCENT = 0x0002; |
| 47 public static final int FLAG_PERMILLE = 0x0004; |
| 48 public static final int FLAG_HAS_EXPONENT = 0x0008; |
| 49 public static final int FLAG_HAS_DEFAULT_CURRENCY = 0x0010; |
| 50 public static final int FLAG_HAS_DECIMAL_SEPARATOR = 0x0020; |
| 51 public static final int FLAG_NAN = 0x0040; |
| 52 public static final int FLAG_INFINITY = 0x0080; |
| 53 public static final int FLAG_FAIL = 0x0100; |
| 54 |
| 55 /** A Comparator that favors ParsedNumbers with the most chars consumed. */ |
| 56 public static final Comparator<ParsedNumber> COMPARATOR = new Comparator<Par
sedNumber>() { |
| 57 @Override |
| 58 public int compare(ParsedNumber o1, ParsedNumber o2) { |
| 59 return o1.charsConsumed - o2.charsConsumed; |
| 60 } |
| 61 }; |
| 62 |
| 63 public ParsedNumber() { |
| 64 clear(); |
| 65 } |
| 66 |
| 67 /** |
| 68 * Clears the data from this ParsedNumber, in effect failing the current par
se. |
| 69 */ |
| 70 public void clear() { |
| 71 quantity = null; |
| 72 charsConsumed = 0; |
| 73 flags = 0; |
| 74 prefix = null; |
| 75 suffix = null; |
| 76 currencyCode = null; |
| 77 } |
| 78 |
| 79 public void copyFrom(ParsedNumber other) { |
| 80 quantity = other.quantity == null ? null : (DecimalQuantity_DualStorageB
CD) other.quantity.createCopy(); |
| 81 charsConsumed = other.charsConsumed; |
| 82 flags = other.flags; |
| 83 prefix = other.prefix; |
| 84 suffix = other.suffix; |
| 85 currencyCode = other.currencyCode; |
| 86 } |
| 87 |
| 88 public void setCharsConsumed(StringSegment segment) { |
| 89 charsConsumed = segment.getOffset(); |
| 90 } |
| 91 |
| 92 /** |
| 93 * Returns whether this the parse was successful. To be successful, at leas
t one char must have been consumed, |
| 94 * and the failure flag must not be set. |
| 95 */ |
| 96 public boolean success() { |
| 97 return charsConsumed > 0 && 0 == (flags & FLAG_FAIL); |
| 98 } |
| 99 |
| 100 public boolean seenNumber() { |
| 101 return quantity != null || 0 != (flags & FLAG_NAN) || 0 != (flags & FLAG
_INFINITY); |
| 102 } |
| 103 |
| 104 public Number getNumber() { |
| 105 return getNumber(false); |
| 106 } |
| 107 |
| 108 public Number getNumber(boolean forceBigDecimal) { |
| 109 boolean sawNegative = 0 != (flags & FLAG_NEGATIVE); |
| 110 boolean sawNaN = 0 != (flags & FLAG_NAN); |
| 111 boolean sawInfinity = 0 != (flags & FLAG_INFINITY); |
| 112 |
| 113 // Check for NaN, infinity, and -0.0 |
| 114 if (sawNaN) { |
| 115 return Double.NaN; |
| 116 } |
| 117 if (sawInfinity) { |
| 118 if (sawNegative) { |
| 119 return Double.NEGATIVE_INFINITY; |
| 120 } else { |
| 121 return Double.POSITIVE_INFINITY; |
| 122 } |
| 123 } |
| 124 if (quantity.isZero() && sawNegative) { |
| 125 return -0.0; |
| 126 } |
| 127 |
| 128 if (quantity.fitsInLong() && !forceBigDecimal) { |
| 129 long l = quantity.toLong(); |
| 130 if (0 != (flags & FLAG_NEGATIVE)) { |
| 131 l *= -1; |
| 132 } |
| 133 return l; |
| 134 } |
| 135 |
| 136 BigDecimal d = quantity.toBigDecimal(); |
| 137 if (0 != (flags & FLAG_NEGATIVE)) { |
| 138 d = d.negate(); |
| 139 } |
| 140 // Special case: MIN_LONG |
| 141 if (d.compareTo(BigDecimal.valueOf(Long.MIN_VALUE)) == 0 && !forceBigDec
imal) { |
| 142 return Long.MIN_VALUE; |
| 143 } |
| 144 return d; |
| 145 |
| 146 } |
| 147 } |
LEFT | RIGHT |