Files
jpexs-decompiler/trunk/src/com/jpexs/decompiler/flash/ecma/EcmaScript.java
T

296 lines
9.0 KiB
Java

/*
* Copyright (C) 2013 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.ecma;
/**
*
* @author JPEXS
*/
public class EcmaScript {
public static Double toNumber(Object o) {
if (o == null) {
return 0.0;
}
if (o instanceof Undefined) {
return Double.NaN;
}
if (o instanceof Null) {
return 0.0;
}
if (o instanceof Boolean) {
return (Boolean) o ? 1.0 : 0.0;
}
if (o instanceof Double) {
return (Double) o;
}
if (o instanceof Long) {
return (double) (long) (Long) o;
}
if (o instanceof Integer) {
return (double) (int) (Integer) o;
}
if (o instanceof String) {
try {
return Double.parseDouble((String) o);
} catch (NumberFormatException nfe) {
return Double.NaN;
}
}
//TODO:ToPrimitive
return 0.0;
}
public static EcmaType type(Object o) {
if (o == null) {
return EcmaType.NULL;
}
if (o.getClass() == String.class) {
return EcmaType.STRING;
}
if (o.getClass() == Integer.class) {
return EcmaType.NUMBER;
}
if (o.getClass() == Double.class) {
return EcmaType.NUMBER;
}
if (o.getClass() == Long.class) {
return EcmaType.NUMBER;
}
if (o.getClass() == Null.class) {
return EcmaType.NULL;
}
if (o.getClass() == Undefined.class) {
return EcmaType.UNDEFINED;
}
return EcmaType.OBJECT;
}
public static Object compare(Object x, Object y) {
Object px = x;
Object py = y;
/*if (leftFirst) {
px = x; //toPrimitive
py = y; //toPrimitive
} else {
py = y; //toPrimitive
px = x; //toPrimitive
}*/
if (type(px) != EcmaType.STRING || type(py) != EcmaType.STRING) {
Double nx = toNumber(px);
Double ny = toNumber(py);
if (nx.isNaN()) {
return new Undefined();
}
if (ny.isNaN()) {
return new Undefined();
}
if (((Double) nx).compareTo((Double) ny) == 0) {
return false;
}
if ((Double.compare((Double) nx, -0.0) == 0) && (Double.compare((Double) ny, 0.0) == 0)) {
return false;
}
if ((Double.compare((Double) nx, 0.0) == 0) && (Double.compare((Double) ny, -0.0) == 0)) {
return false;
}
if (nx.isInfinite() && nx > 0) {
return false;
}
if (ny.isInfinite() && ny > 0) {
return true;
}
if (nx.isInfinite() && nx < 0) {
return false;
}
if (ny.isInfinite() && ny < 0) {
return true;
}
if (nx.compareTo(ny) < 0) {
return true;
}
return false;
} else {//Both are STRING
String sx = (String) px;
String sy = (String) py;
if (sx.startsWith(sy)) {
return false;
}
if (sy.startsWith(sx)) {
return true;
}
int len = sx.length() > sy.length() ? sx.length() : sy.length();
for (int k = 0; k < len; k++) {
int m = 0;
int n = 0;
if (sx.length() > k) {
m = sx.charAt(k);
}
if (sy.length() > k) {
n = sy.charAt(k);
}
if (m != n) {
if (m < n) {
return true;
} else {
return false;
}
}
}
return false;
}
}
public static boolean equals(Object x, Object y) {
EcmaType typeX = type(x);
EcmaType typeY = type(y);
if (typeX == typeY) {
if (typeX == null) {
return true;
}
if (typeX == EcmaType.NULL) {
return true;
}
if (typeX == EcmaType.UNDEFINED) {
return true;
}
if (typeX == EcmaType.NUMBER) {
if (x instanceof Integer) {
x = Double.valueOf((Integer) x);
}
if (x instanceof Long) {
x = Double.valueOf((Long) x);
}
if (y instanceof Integer) {
y = Double.valueOf((Integer) y);
}
if (y instanceof Long) {
y = Double.valueOf((Long) y);
}
if (((Double) x).isNaN()) {
return false;
}
if (((Double) y).isNaN()) {
return false;
}
if (((Double) x).compareTo((Double) y) == 0) {
return true;
}
if ((Double.compare((Double) x, -0.0) == 0) && (Double.compare((Double) y, 0.0) == 0)) {
return true;
}
if ((Double.compare((Double) x, 0.0) == 0) && (Double.compare((Double) y, -0.0) == 0)) {
return true;
}
return false;
}
if (typeX == EcmaType.STRING) {
return ((String) x).equals((String) y);
}
if (typeX == EcmaType.BOOLEAN) {
return x == y;
}
return x == y;
}
if ((typeX == EcmaType.NULL) && (typeY == EcmaType.UNDEFINED)) {
return true;
}
if ((typeX == EcmaType.UNDEFINED) && (typeY == EcmaType.NULL)) {
return true;
}
if ((typeX == EcmaType.NUMBER) && (typeY == EcmaType.STRING)) {
return equals(x, toNumber(y));
}
if ((typeX == EcmaType.STRING) && (typeY == EcmaType.NUMBER)) {
return equals(toNumber(x), y);
}
if (typeX == EcmaType.BOOLEAN) {
return equals(toNumber(x), y);
}
if (typeY == EcmaType.BOOLEAN) {
return equals(x, toNumber(y));
}
if (typeX == EcmaType.STRING || typeX == EcmaType.NUMBER) {
//y is object
//return ecmaEquals(ecmaToPrimitive(x), y);
}
if (typeY == EcmaType.STRING || typeY == EcmaType.NUMBER) {
//x is object
//return ecmaEquals(x, ecmaToPrimitive(y));
}
return false;
}
public static boolean toBoolean(Object o) {
if (o == null) {
return false;
}
if (o instanceof Undefined) {
return false;
}
if (o instanceof Null) {
return false;
}
if (o instanceof Boolean) {
return (Boolean) o;
}
if (o instanceof Long) {
return ((Long) o) != 0;
}
if (o instanceof Integer) {
return ((Integer) o) != 0;
}
if (o instanceof Double) {
Double d = (Double) o;
if (d.isNaN()) {
return false;
}
if (Double.compare(d, 0) == 0) {
return false;
}
return true;
}
if (o instanceof String) {
String s = (String) o;
return !s.isEmpty();
}
return true; //other Object
}
public static Long toUint32(Object o) {
Double n = toNumber(o);
if (n.isNaN()) {
return 0L;
}
if (Double.compare(n, 0.0) == 0) {
return 0L;
}
if (Double.compare(n, -0.0) == 0) {
return 0L;
}
if (Double.isInfinite(n)) {
return 0L;
}
Long posInt = (long) (double) (Math.signum(n) * Math.floor(Math.abs(n)));
posInt %= (1 << 32);
return posInt;
}
}