1579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/* 2579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Copyright (C) 2011 The Android Open Source Project 3579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 4579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License"); 5579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * you may not use this file except in compliance with the License. 6579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * You may obtain a copy of the License at 7579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 8579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * http://www.apache.org/licenses/LICENSE-2.0 9579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 10579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Unless required by applicable law or agreed to in writing, software 11579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS, 12579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * See the License for the specific language governing permissions and 14579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * limitations under the License. 15579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 16579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 17579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonpackage com.android.dx.io; 18579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 19579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.io.instructions.DecodedInstruction; 20579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.util.DexException; 21579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 22579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/** 23579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Walks through a block of code and calls visitor call backs. 24579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 25579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonpublic final class CodeReader { 26579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private Visitor fallbackVisitor = null; 27579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private Visitor stringVisitor = null; 28579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private Visitor typeVisitor = null; 29579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private Visitor fieldVisitor = null; 30579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private Visitor methodVisitor = null; 31579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 32579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 33579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Sets {@code visitor} as the visitor for all instructions. 34579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 35579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void setAllVisitors(Visitor visitor) { 36579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fallbackVisitor = visitor; 37579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson stringVisitor = visitor; 38579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson typeVisitor = visitor; 39579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fieldVisitor = visitor; 40579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson methodVisitor = visitor; 41579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 42579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 43579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 44579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Sets {@code visitor} as the visitor for all instructions not 45579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * otherwise handled. 46579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 47579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void setFallbackVisitor(Visitor visitor) { 48579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fallbackVisitor = visitor; 49579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 50579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 51579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 52579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Sets {@code visitor} as the visitor for all string instructions. 53579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 54579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void setStringVisitor(Visitor visitor) { 55579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson stringVisitor = visitor; 56579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 57579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 58579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 59579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Sets {@code visitor} as the visitor for all type instructions. 60579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 61579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void setTypeVisitor(Visitor visitor) { 62579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson typeVisitor = visitor; 63579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 64579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 65579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 66579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Sets {@code visitor} as the visitor for all field instructions. 67579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 68579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void setFieldVisitor(Visitor visitor) { 69579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fieldVisitor = visitor; 70579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 71579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 72579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 73579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Sets {@code visitor} as the visitor for all method instructions. 74579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 75579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void setMethodVisitor(Visitor visitor) { 76579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson methodVisitor = visitor; 77579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 78579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 79579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void visitAll(DecodedInstruction[] decodedInstructions) 80579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throws DexException { 81579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int size = decodedInstructions.length; 82579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 83579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson for (int i = 0; i < size; i++) { 84579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson DecodedInstruction one = decodedInstructions[i]; 85579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (one == null) { 86579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson continue; 87579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 88579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 89579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson callVisit(decodedInstructions, one); 90579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 91579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 92579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 93579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void visitAll(short[] encodedInstructions) throws DexException { 94579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson DecodedInstruction[] decodedInstructions = 95579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson DecodedInstruction.decodeAll(encodedInstructions); 96579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson visitAll(decodedInstructions); 97579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 98579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 99579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private void callVisit(DecodedInstruction[] all, DecodedInstruction one) { 100579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Visitor visitor = null; 101579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 102579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson switch (OpcodeInfo.getIndexType(one.getOpcode())) { 103579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson case STRING_REF: visitor = stringVisitor; break; 104579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson case TYPE_REF: visitor = typeVisitor; break; 105579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson case FIELD_REF: visitor = fieldVisitor; break; 106579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson case METHOD_REF: visitor = methodVisitor; break; 107579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 108579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 109579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (visitor == null) { 110579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson visitor = fallbackVisitor; 111579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 112579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 113579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (visitor != null) { 114579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson visitor.visit(all, one); 115579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 116579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 117579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 118579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public interface Visitor { 119579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson void visit(DecodedInstruction[] all, DecodedInstruction one); 120579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 121579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson} 122