package tv.porst.swfretools.utils.as3;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import tv.porst.swfretools.parser.structures.AS3Data;
import tv.porst.swfretools.parser.structures.MultinameInfo;
import tv.porst.swfretools.parser.structures.MultinameInfoList;
import tv.porst.swfretools.utils.ActionScript3Helpers;
import tv.porst.swfretools.utils.ResolverException;
/**
* Represents ActionScript 3 data in a way that is easier to work with than
* the standard representation as directly parsed from a SWF file.
*/
public final class ResolvedCode {
/**
* The parsed ActionScript 3 data this class represents.
*/
private final AS3Data data;
/**
* The resolved classes that are part of the ActionScript 3 data.
*/
private final List<ResolvedClass> classes;
/**
* Map that caches multinames.
*/
private final Map<Integer, String[]> resolvedMultinames = new HashMap<Integer, String[]>();
/**
* Creates a new resolved code object.
*
* @param data The parsed ActionScript 3 data this class represents.
* @param classes The resolved classes that are part of the ActionScript 3 data.
*/
public ResolvedCode(final AS3Data data, final List<ResolvedClass> classes) {
if (data == null) {
throw new IllegalArgumentException("Data argument must not be null.");
}
if (classes == null) {
throw new IllegalArgumentException("Classes argument must not be null.");
}
this.data = data;
this.classes = new ArrayList<ResolvedClass>(classes);
}
/**
* Returns the resolved classes that are part of the ActionScript 3 data.
*
* @return The resolved classes that are part of the ActionScript 3 data.
*/
public List<ResolvedClass> getClasses() {
return new ArrayList<ResolvedClass>(classes);
}
/**
* Returns the parsed ActionScript 3 data this class represents.
*
* @return The parsed ActionScript 3 data this class represents.
*/
public AS3Data getData() {
return data;
}
/**
* Returns a double value from the double constants table.
*
* @param index Index into the table.
*
* @return The indexed double value.
*/
public Double resolveDouble(final int index) {
if (index < 0) {
throw new IllegalArgumentException("Index value must not be negative");
}
if (index >= data.getConstantPool().getDoubles().size()) {
return null;
}
else {
return data.getConstantPool().getDoubles().get(index).value();
}
}
/**
* Returns an integer value from the integer constants table.
*
* @param index Index into the table.
*
* @return The indexed integer value.
*/
public Long resolveInteger(final int index) {
if (index < 0) {
throw new IllegalArgumentException("Index value must not be negative");
}
if (index >= data.getConstantPool().getIntegers().size()) {
return null;
}
else {
return data.getConstantPool().getIntegers().get(index).value();
}
}
/**
* Returns a multiname value from the multiname constants table.
*
* @param index Index into the table.
*
* @return The indexed multiname value.
*/
public String[] resolveMultiname(final int index) {
if (index < 0) {
throw new IllegalArgumentException("Index value must not be negative");
}
if (resolvedMultinames.containsKey(index)) {
return resolvedMultinames.get(index);
}
final MultinameInfoList multinames = data.getConstantPool().getMultinames();
final MultinameInfo multiname = multinames.get(index - 1);
try {
final String[] namespaceParts = ActionScript3Helpers.resolveMultiname(multiname, data.getConstantPool().getStrings(), data.getConstantPool().getNamespaces());
resolvedMultinames.put(index, namespaceParts);
return namespaceParts;
} catch (final ResolverException e) {
return null;
}
}
/**
* Returns a string value from the namespace constants table.
*
* @param index Index into the table.
*
* @return The indexed namespace value.
*/
public String resolveNamespace(final int index) {
if (index < 0) {
throw new IllegalArgumentException("Index value must not be negative");
}
if (index >= data.getConstantPool().getNamespaces().size()) {
return null;
}
else {
final int nameIndex = data.getConstantPool().getNamespaces().get(index).getName().value();
return nameIndex == 0 ? "" : resolveString(nameIndex);
}
}
/**
* Returns a string value from the string constants table.
*
* @param index Index into the table.
*
* @return The indexed string value.
*/
public String resolveString(final int index) {
if (index < 0) {
throw new IllegalArgumentException("Index value must not be negative");
}
if (index >= data.getConstantPool().getStrings().size()) {
return null;
}
else {
return data.getConstantPool().getStrings().get(index).getName().value();
}
}
/**
* Returns an unsigned integer value from the unsigned integer constants table.
*
* @param index Index into the table.
*
* @return The indexed unsigned integer value.
*/
public Long resolveUInteger(final int index) {
if (index < 0) {
throw new IllegalArgumentException("Index value must not be negative");
}
if (index >= data.getConstantPool().getUintegers().size()) {
return null;
}
else {
return data.getConstantPool().getUintegers().get(index).value();
}
}
}