// Copyright (C) 2005 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.caja.parser.js;
import com.google.caja.lexer.FilePosition;
import com.google.caja.parser.ParseTreeNode;
import com.google.caja.reporting.RenderContext;
import java.util.List;
/**
* A number literal that was specified in hex or octal notation, or whose
* decimal form had no decimal point.
*
* @author mikesamuel@gmail.com
*/
public final class IntegerLiteral extends NumberLiteral {
private static final long serialVersionUID = -8933353016397006347L;
/**
* The minimum value that can be represented in IEEE-754 64b floating point.
* With a 52 bit mantissa, this is -(1 << 52).
*/
public static final long MIN_VALUE = -0x0010000000000000L;
/**
* The maximum value that can be represented in IEEE-754 64b floating point.
* With a 52 bit mantissa, this is (1 << 52). Note, that this is symmetric
* with MIN_VALUE instead of being 1 less, since IEEE-754 uses unsigned
* mantissas -- no 2's complement.
*/
public static final long MAX_VALUE = 0x0010000000000000L;
/**
* Restricted to the range of integers supported by a 64bit IEEE floating
* point value.
* @see #MIN_VALUE
* @see #MAX_VALUE
*/
private final long value;
/** @param children unused. This ctor is provided for reflection. */
@ReflectiveCtor
public IntegerLiteral(
FilePosition pos, Number value, List<? extends ParseTreeNode> children) {
this(pos, value.longValue());
}
public IntegerLiteral(FilePosition pos, long value) {
super(pos);
if (MIN_VALUE > value || value > MAX_VALUE) {
throw new IllegalArgumentException("" + value);
}
this.value = value;
}
@Override
public Number getValue() { return Long.valueOf(value); }
@Override
public double doubleValue() { return value; }
@Override
public void render(RenderContext rc) {
long n = getValue().longValue();
// Use hex if it would be shorter.
// The hex form requires a "0x" at the front so will be shorter at the
// inequality:
// log(n) / log(10) = 2 + log(n) / log(16)
// log(n) * log(16) = 2 * log(10) * log(16) + log(n) * log(10)
// log(n) * (log(16) - log(10)) = 2 * log(10) * log(16)
// log(n) * log(1.6) = 2 * log(10) * log(16)
// log(n) = 2 * log(10) * log(16) / log(1.6)
// n = e ** (2 * log(10) * log(16) / log(1.6))
// 9 < n < 10
String str;
if ((-1L << 36) > n && n < (1L << 36)) {
str = Long.toString(n, 16);
if (str.charAt(0) == '-') {
str = "-0x" + str.substring(1);
} else {
str = "0x" + str;
}
} else {
str = Long.toString(n, 10);
}
rc.getOut().consume(str);
}
}