private NumberConstant getDoubleValueOrInt(String str, boolean force, TypeValue[] ppType) {
Double d;
double sum = 0;
if (str.equals("NaN")) {
ppType[0] = cx.doubleType();
return new DoubleNumberConstant(Double.NaN);
}
else if (str.equals("Infinity")){
ppType[0] = cx.doubleType();
return new DoubleNumberConstant(Double.POSITIVE_INFINITY);
}
else if (str.equals("-Infinity")){
ppType[0] = cx.doubleType();
return new DoubleNumberConstant(Double.NEGATIVE_INFINITY);
}
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
d = Double.valueOf(str);
sum = d.doubleValue();
}
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(0);
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
while (startIndex < (len-1) && str.charAt(startIndex) == '0')
startIndex++;
String str2 = str.substring(startIndex, len); // need to count bits of precision starting from first nonzero digit
len -= startIndex; // Necessary to accurately detect when we've read more
startIndex = 0; // than 53 bits worth of mantissa data (where roundoff error occurs).
int newDigit = 0;
int end;
boolean roundUp = false;
switch(base)
{
case 10:
for (end=startIndex; end < len; end++)
{
newDigit = str2.charAt(end) - '0';
sum = sum*base + newDigit;
}
if (sum > 2147483647) // i.e. biggest integer possible. After that, error creeps into the above calculation.
{
d = Double.valueOf(str2);
sum = d.doubleValue();
}
break;
case 16:
for (end=startIndex; end*4 < 53; end++) // 4 bits of precision per digit, 4*13=52
{
if (end >= len) // out of bits before 52
break;
newDigit = unHex(str2.charAt(end));
sum = sum*base + newDigit;
}
if (end < len) // If number contains more than 53 bits of precision, may need to roundUp last digit processed.
{
int bit53 = (newDigit & 0x1);
newDigit = unHex(str2.charAt(end));
int bit54 = (newDigit & 0x8) >> 3; // the 54th bit is the first to be dropped from the mantissa.
roundUp = (newDigit & 0x7) != 0; // check if any bit after bit54 is set
double factor = base;
while(++end < len)
{
newDigit = unHex(str2.charAt(end));
roundUp |= (newDigit != 0); // any trailing positive bit causes us to round up
factor *= base;
}
roundUp = (bit54 != 0) && ( (bit53 != 0) || roundUp);
sum += (roundUp ? 1.0 : 0.0);
sum *= factor;
}
break;
}
// negate if needed
if (negative) {
if (sum == 0.0) {
d = Double.valueOf("-0");
sum = d.doubleValue();
isInt = false; // can't represent -0 as an int
}
else
sum = -sum;
}
}
if (!force && isInt) {
// value is integral. See if it fits in a smaller type
long ival = (long)sum;
if ((Integer.MIN_VALUE <= ival) && (ival <= Integer.MAX_VALUE)) {
ppType[0] = cx.intType();
return new IntNumberConstant((int)ival);
}
// don't make it uint unless ES4
else if (cx.statics.es4_numerics && (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.doubleType();
// canonicalize NaN and Infinity
d = Double.valueOf(sum);
if (d.isNaN())
d = Double.NaN;
else if (d.isInfinite()) {
if (str.charAt(0) == '-')
d = Double.NEGATIVE_INFINITY;
else
d = Double.POSITIVE_INFINITY;
}
return new DoubleNumberConstant(d.doubleValue());
}