/* * 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; import com.jpexs.decompiler.flash.abc.types.ClassInfo; import com.jpexs.decompiler.flash.abc.types.InstanceInfo; import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.abc.types.MethodInfo; import com.jpexs.decompiler.flash.abc.types.traits.Trait; import com.jpexs.decompiler.flash.abc.types.traits.TraitClass; import com.jpexs.decompiler.flash.abc.types.traits.TraitFunction; import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter; import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * * @author JPEXS */ public class ABCMethodIndexing { private final ABC abc; private Map<MethodInfo, Integer> bodyIdxFromMethod = new HashMap<>(); public ABCMethodIndexing(ABC abc) { this.abc = abc; createBodyIdxFromMethodIdxMap(abc); } public final void createBodyIdxFromMethodIdxMap(ABC abc) { List<MethodBody> bodies = abc.bodies; Map<MethodInfo, Integer> map = new HashMap<>(bodies.size()); for (int i = 0; i < bodies.size(); i++) { MethodBody mb = bodies.get(i); map.put(abc.method_info.get(mb.method_info), i); } bodyIdxFromMethod = map; } public int findMethodBodyIndex(MethodInfo methodInfo) { Integer bi = bodyIdxFromMethod.get(methodInfo); if (bi == null) { return -1; } return bi; } public int findMethodBodyIndex(int methodInfo) { if (methodInfo < 0 || methodInfo >= abc.method_info.size()) { return -1; } MethodInfo mi = abc.method_info.get(methodInfo); return findMethodBodyIndex(mi); } public MethodBody findMethodBody(MethodInfo methodInfo) { int bi = findMethodBodyIndex(methodInfo); if (bi != -1) { return abc.bodies.get(bi); } return null; } public MethodBody findMethodBody(int methodInfo) { int bi = findMethodBodyIndex(methodInfo); if (bi != -1) { return abc.bodies.get(bi); } return null; } public List<Trait> findMethodTraits(ScriptPack pack, int bodyIndex) { int methodInfo = abc.bodies.get(bodyIndex).method_info; List<Trait> traits = abc.script_info.get(pack.scriptIndex).traits.traits; List<Trait> resultTraits = new ArrayList<>(); for (int ti : pack.traitIndices) { Trait t = traits.get(ti); findTraits(abc, t, methodInfo, resultTraits); } return resultTraits; } private static void findTraits(ABC abc, Trait trait, int methodInfo, List<Trait> result) { if (trait instanceof TraitSlotConst) { TraitSlotConst tsc = (TraitSlotConst) trait; } else if (trait instanceof TraitFunction) { TraitFunction tf = (TraitFunction) trait; if (tf.method_info == methodInfo) { result.add(trait); } } else if (trait instanceof TraitMethodGetterSetter) { TraitMethodGetterSetter tmgs = (TraitMethodGetterSetter) trait; if (tmgs.method_info == methodInfo) { result.add(trait); } } else if (trait instanceof TraitClass) { TraitClass tc = (TraitClass) trait; InstanceInfo instanceInfo = abc.instance_info.get(tc.class_info); for (Trait t : instanceInfo.instance_traits.traits) { findTraits(abc, t, methodInfo, result); } ClassInfo classInfo = abc.class_info.get(tc.class_info); for (Trait t : classInfo.static_traits.traits) { findTraits(abc, t, methodInfo, result); } } } }