in java/dfp/src/main/java/com/epam/deltix/dfp/JavaImpl.java [1468:1653]
static long parse(final CharSequence s, final int si, final int ei, final int roundingMode, final String decimalMarks) {
char c;
int p = si;
boolean sign = false;
c = s.charAt(p);
if (c == '+') {
p += 1;
c = p < ei ? s.charAt(p) : 0;
}
if (c == '-') {
sign = true;
p += 1;
c = p < ei ? s.charAt(p) : 0;
}
if (decimalMarks.indexOf(c) < 0 && (c < '0' || c > '9')) {
if (TextUtils.equalsIgnoringCase(s, p, ei, "Infinity") ||
TextUtils.equalsIgnoringCase(s, p, ei, "Inf"))
return sign ? JavaImpl.NEGATIVE_INFINITY : JavaImpl.POSITIVE_INFINITY;
if (TextUtils.equalsIgnoringCase(s, p, ei, "NaN") ||
TextUtils.equalsIgnoringCase(s, p, ei, "SNaN"))
return JavaImpl.NaN;
throw invalidFormat(s, si, ei);
}
boolean seenRadixPoint = false;
int leadingZerosAfterPoint = 0;
if (c == '0' || decimalMarks.indexOf(c) >= 0) {
if (decimalMarks.indexOf(c) >= 0) {
seenRadixPoint = true;
p += 1;
c = p < ei ? s.charAt(p) : 0;
}
while (c == '0') {
p += 1;
c = p < ei ? s.charAt(p) : 0;
if (seenRadixPoint)
leadingZerosAfterPoint += 1;
if (decimalMarks.indexOf(c) >= 0) {
if (seenRadixPoint)
throw invalidFormat(s, si, ei);
seenRadixPoint = true;
p += 1;
c = p < ei ? s.charAt(p) : 0;
if (c == 0)
return makeZero(sign, EXPONENT_BIAS - leadingZerosAfterPoint);
} else if (c == 0) {
return makeZero(sign, EXPONENT_BIAS - leadingZerosAfterPoint);
}
}
}
int numberOfDigits = 0;
int decimalExponentScale = 0;
long coefficient = 0;
boolean roundedUp = false, rounded = false, midpoint = false;
int additionalExponent = 0;
while ((c >= '0' && c <= '9') || decimalMarks.indexOf(c) >= 0) {
if (decimalMarks.indexOf(c) >= 0) {
if (seenRadixPoint)
throw invalidFormat(s, si, ei);
seenRadixPoint = true;
p += 1;
c = p < ei ? s.charAt(p) : 0;
continue;
}
if (seenRadixPoint)
decimalExponentScale += 1;
numberOfDigits += 1;
if (numberOfDigits <= 16) {
coefficient = (coefficient << 1) + (coefficient << 3) + c - '0';
} else if (numberOfDigits == 17) {
switch (roundingMode) {
case BID_ROUNDING_EXCEPTION:
throw new NumberFormatException("Can't convert string(='" + s.subSequence(si, ei) + "') to Decimal64 without precision loss.");
case BID_ROUNDING_TO_NEAREST:
midpoint = (c == '5' && (coefficient & 1) == 0);
if (c > '5' || (c == '5' && (coefficient & 1) != 0)) {
coefficient += 1;
roundedUp = true;
}
break;
case BID_ROUNDING_DOWN:
if (sign) {
coefficient += 1;
roundedUp = true;
}
break;
case BID_ROUNDING_UP:
if (!sign) {
coefficient += 1;
roundedUp = true;
}
break;
case BID_ROUNDING_TIES_AWAY:
if (c >= '5') {
coefficient += 1;
roundedUp = true;
}
break;
}
if (coefficient == 10000000000000000L) {
coefficient = 1000000000000000L;
additionalExponent = 1;
}
if (c > '0')
rounded = true;
additionalExponent += 1;
} else {
additionalExponent += 1;
if (midpoint && c >= '0') {
coefficient += 1;
midpoint = false;
roundedUp = true;
}
if (c >= '0')
rounded = true;
}
p += 1;
c = p < ei ? s.charAt(p) : 0;
}
additionalExponent -= (decimalExponentScale + leadingZerosAfterPoint);
if (c == 0)
return fastPackCheckOverflow(sign, additionalExponent + EXPONENT_BIAS, coefficient);
if (c != 'E' && c != 'e')
throw invalidFormat(s, si, ei);
p += 1;
c = p < ei ? s.charAt(p) : 0;
final boolean isExponentSigned = c == '-';
if (c == '-' || c == '+') {
p += 1;
c = p < ei ? s.charAt(p) : 0;
}
if (c == 0 || c < '0' || c > '9')
throw invalidFormat(s, si, ei);
int exponent = 0;
while (c >= '0' && c <= '9') {
if (exponent < (1 << 20)) {
exponent = (exponent << 1) + (exponent << 3) + (c - '0');
p += 1;
c = p < ei ? s.charAt(p) : 0;
}
}
if (c != 0)
throw invalidFormat(s, si, ei);
if (isExponentSigned)
exponent = -exponent;
exponent += additionalExponent + EXPONENT_BIAS;
if (exponent < 0) {
if (roundedUp)
coefficient -= 1;
return packUnderflow(sign, exponent, coefficient, rounded, BID_ROUNDING_TO_NEAREST);
}
return pack(sign ? MASK_SIGN : 0, exponent, coefficient, BID_ROUNDING_TO_NEAREST);
}