/*
* Copyright (C) 2010-2016 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
package com.jpexs.decompiler.flash.abc.avm2.model;
import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instructions;
import com.jpexs.decompiler.flash.abc.avm2.parser.script.AVM2SourceGenerator;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.ecma.EcmaScript;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.graph.CompilationException;
import com.jpexs.decompiler.graph.DottedChain;
import com.jpexs.decompiler.graph.GraphSourceItem;
import com.jpexs.decompiler.graph.GraphTargetItem;
import com.jpexs.decompiler.graph.SourceGenerator;
import com.jpexs.decompiler.graph.TypeItem;
import com.jpexs.decompiler.graph.model.IntegerValueTypeItem;
import com.jpexs.decompiler.graph.model.LocalData;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
*
* @author JPEXS
*/
public class IntegerValueAVM2Item extends NumberValueAVM2Item implements IntegerValueTypeItem {
public Long value;
public IntegerValueAVM2Item(GraphSourceItem instruction, GraphSourceItem lineStartIns, Long value) {
super(instruction, lineStartIns);
this.value = value;
}
@Override
public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) {
if (Configuration.smartNumberFormatting.get()) {
if (value >= 256 && value <= 0xffffffffL) {
int intVal = (int) (long) (value & 0xffffff);
int r = (intVal >> 16) & 0xff;
int g = (intVal >> 8) & 0xff;
int b = intVal & 0xff;
if ((r == b && b == g) // gray
|| (((intVal & 0x0f0000) == 0 || (intVal & 0x0f0000) == 0x0f0000) // a(0/F)b(0/F)c(0/F)
&& ((intVal & 0x000f00) == 0 || (intVal & 0x000f00) == 0x000f00)
&& ((intVal & 0x00000f) == 0 || (intVal & 0x00000f) == 0x00000f))
|| ((((intVal & 0xf00000) >> 20) == ((intVal & 0x0f0000) >> 16)) // aabbcc
&& (((intVal & 0x00f000) >> 12) == ((intVal & 0x000f00) >> 8))
&& (((intVal & 0x0000f0) >> 4) == ((intVal & 0x00000f))))) {
return writer.append("0x").append(Long.toHexString(value));
}
}
long value2 = (long) value;
if (value2 > 0 && value2 % 60 == 0) {
int thousandCount = 0;
value2 /= 60;
boolean isHour = false;
boolean isDay = false;
if (value2 % 60 == 0) {
value2 /= 60;
isHour = true;
if (value2 % 24 == 0) {
value2 /= 24;
isDay = true;
}
}
// check milli, micro and nanoseconds
while (thousandCount < 3) {
if (value2 % 1000 == 0) {
thousandCount++;
value2 /= 1000;
} else {
break;
}
}
if (value2 < 1000) {
List<Integer> factors = new ArrayList<>();
if (value2 > 1) {
factors.add((int) value2);
}
if (isDay) {
factors.add(24);
}
if (isHour) {
factors.add(60);
}
factors.add(60);
for (int i = 0; i < thousandCount; i++) {
factors.add(1000);
}
for (int i = 0; i < factors.size(); i++) {
if (i != 0) {
writer.append(" * ");
}
writer.append(factors.get(i));
}
return writer;
}
}
}
return writer.append(EcmaScript.toString(value));
}
@Override
public Object getResult() {
return value;//(Double) (double) (long) value;
}
@Override
public boolean isCompileTime(Set<GraphTargetItem> dependencies) {
return true;
}
@Override
public List<GraphSourceItem> toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException {
AVM2Instruction ins;
if (value >= -128 && value <= 127) {
ins = new AVM2Instruction(0, AVM2Instructions.PushByte, new int[]{(int) (long) value});
} else if (value >= -32768 && value <= 32767) {
ins = new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{((int) (long) value) & 0xffff});
} else {
ins = new AVM2Instruction(0, AVM2Instructions.PushInt, new int[]{((AVM2SourceGenerator) generator).abcIndex.getSelectedAbc().constants.getIntId(value, true)});
}
return toSourceMerge(localData, generator, ins);
}
@Override
public GraphTargetItem returnType() {
return new TypeItem(DottedChain.INT);
}
@Override
public boolean hasReturnValue() {
return true;
}
@Override
public int intValue() {
return (int) (long) value;
}
}