private NumberConstant getDecimalValueOrInt(String str, boolean force, TypeValue[] ppType) {
// convert str into a decimal128 value.
// if force, return a decimal128 for sure, otherwise return int or uint if value will fit
// check for NaN and Infinity
Decimal128 dval;
if (str.equals("NaN")) {
ppType[0] = cx.decimalType();
return new DecimalNumberConstant(Decimal128.NaN);
}
else if (str.equals("Infinity")){
ppType[0] = cx.decimalType();
return new DecimalNumberConstant(Decimal128.INFINITY);
}
else if (str.equals("-Infinity")){
ppType[0] = cx.decimalType();
return new DecimalNumberConstant(Decimal128.NEGINFINITY);
}
boolean isInt = false;
if ((str.indexOf(".") > -1 || str.indexOf("e") > -1 ||
str.indexOf("E") > -1 || str.length() > 10) &&
!(str.indexOf("x") > -1 || str.indexOf("X") > -1)) {
// looks like floating, and not hex
dval = new Decimal128(str);
}
else {
// looks like an integral value. It could be hex
isInt = true;
int base = 10;
int startIndex = 0;
int len = str.length();
boolean negative = false;
if (len > 1) {
char c0 = str.charAt(startIndex);
if ((c0 == '-') || (c0 == '+')) {
startIndex++;
if (c0 == '-')
negative = true;
}
}
if (len > 2) {
if ( str.charAt(startIndex) == '0') {
startIndex++;
char c0 = str.charAt(startIndex);
if ((c0 == 'x') || (c0 == 'X')) {
base = 16;
startIndex++;
}
}
}
// skip leading zeros, but not the last one
while (startIndex < (len-1) && str.charAt(startIndex) == '0')
startIndex++;
if (base == 10) {
String str2 = str.substring(startIndex, len);
dval = new Decimal128(str2);
}
else { // base == 16
// can we really have hex constants for type decimal?
int end, newDigit;
if (D128_HEXDIGIT == null) {
// wow, somebody is creating a hex Decimal128 value. We'll need digits
D128_HEXDIGIT = new Decimal128[16];
for (int ndx = 0; ndx < 16; ndx++) {
D128_HEXDIGIT[ndx] = new Decimal128(ndx);
}
D128_SIXTEEN = new Decimal128(16);
}
dval = Decimal128.ZERO;
for (end = startIndex; end < len; end++) {
newDigit = unHex(str.charAt(end));
dval = D128_SIXTEEN.multiply(dval).add(D128_HEXDIGIT[newDigit]);
}
}
// negate if needed
if (negative) {
if (dval.equals(Decimal128.ZERO)) {
dval = Decimal128.NEGZERO;
isInt = false;
}
else
dval = Decimal128.ZERO.subtract(dval);
}
}
if (!force && isInt) {
// value is integral. See if it fits in a smaller type
long ival = dval.longValue();
if ((Integer.MIN_VALUE <= ival) && (ival <= Integer.MAX_VALUE)) {
ppType[0] = cx.intType();
return new IntNumberConstant((int)ival);
}
else if ((0 <= ival) && (ival <= MAXUINT)) {
ppType[0] = cx.uintType();
return new UintNumberConstant(ival);
}
}
// either not integral or not small enough to fit in uint or int
ppType[0] = cx.decimalType();
// canonicalize NaN and Infinity
if (dval.isNaN())
dval = Decimal128.NaN;
else if (!dval.isFinite()) {
if (str.charAt(0) == '-')
dval = Decimal128.NEGINFINITY;
else
dval = Decimal128.INFINITY;
}