Parses a decimal number from a CharSequence and stores the result in the provided Decimal instance. This is the main parsing method that handles all decimal formats including scientific notation, special values (NaN/Infinity), and various suffixes. The parser validates precision and scale constr
(Decimal decimal, CharSequence cs, int lo, int hi, int precision, int scale, boolean strict, boolean lossy)
| 112 | * constraints are violated, or if the value exceeds the decimal type's capacity |
| 113 | */ |
| 114 | public static long parse(Decimal decimal, CharSequence cs, int lo, int hi, int precision, int scale, boolean strict, boolean lossy) throws NumericException { |
| 115 | int ch = hi > lo ? cs.charAt(hi - 1) | 32 : 0; |
| 116 | // We don't want to parse the m suffix, we can safely skip it |
| 117 | if (ch == 'm') { |
| 118 | strict = true; |
| 119 | hi--; |
| 120 | ch = hi > lo ? cs.charAt(hi - 1) | 32 : 0; |
| 121 | } |
| 122 | |
| 123 | // We also need to skip 'd' and 'f' when parsing doubles/floats |
| 124 | if (ch == 'f' || ch == 'd') { |
| 125 | hi--; |
| 126 | } |
| 127 | |
| 128 | // Skip leading whitespaces |
| 129 | while (lo < hi && cs.charAt(lo) == ' ') { |
| 130 | lo++; |
| 131 | } |
| 132 | |
| 133 | if (lo == hi) { |
| 134 | throw NumericException.instance().put("invalid decimal: empty value"); |
| 135 | } |
| 136 | |
| 137 | // Parses sign |
| 138 | boolean negative = false; |
| 139 | if (cs.charAt(lo) == '-') { |
| 140 | negative = true; |
| 141 | lo++; |
| 142 | } else if (cs.charAt(lo) == '+') { |
| 143 | lo++; |
| 144 | } |
| 145 | |
| 146 | if (lo == hi) { |
| 147 | throw NumericException.instance().put("invalid decimal: empty value"); |
| 148 | } |
| 149 | |
| 150 | ch = cs.charAt(lo); |
| 151 | if (ch >= 'I') { |
| 152 | if (isNanOrInfinite((char) ch, cs, lo, hi)) { |
| 153 | decimal.ofNull(); |
| 154 | return 0; |
| 155 | } |
| 156 | } |
| 157 | |
| 158 | // Remove leading zeros |
| 159 | boolean skippedZeroes = false; |
| 160 | while (lo < hi - 1 && cs.charAt(lo) == '0') { |
| 161 | lo++; |
| 162 | skippedZeroes = true; |
| 163 | } |
| 164 | |
| 165 | // We do a first pass over the literal to ensure that the format is correct (numerical and at most 1 dot) and to |
| 166 | // measure the given precision/scale. |
| 167 | int dot = -1; |
| 168 | boolean digitFound = false; |
| 169 | int digitLo = lo; |
| 170 | for (; lo < hi; lo++) { |
| 171 | char c = cs.charAt(lo); |