1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.dx.io; 18 19import com.android.dex.DexException; 20import com.android.dx.io.instructions.DecodedInstruction; 21 22/** 23 * Walks through a block of code and calls visitor call backs. 24 */ 25public final class CodeReader { 26 private Visitor fallbackVisitor = null; 27 private Visitor stringVisitor = null; 28 private Visitor typeVisitor = null; 29 private Visitor fieldVisitor = null; 30 private Visitor methodVisitor = null; 31 private Visitor methodAndProtoVisitor = null; 32 private Visitor callSiteVisitor = null; 33 34 /** 35 * Sets {@code visitor} as the visitor for all instructions. 36 */ 37 public void setAllVisitors(Visitor visitor) { 38 fallbackVisitor = visitor; 39 stringVisitor = visitor; 40 typeVisitor = visitor; 41 fieldVisitor = visitor; 42 methodVisitor = visitor; 43 methodAndProtoVisitor = visitor; 44 callSiteVisitor = visitor; 45 } 46 47 /** 48 * Sets {@code visitor} as the visitor for all instructions not 49 * otherwise handled. 50 */ 51 public void setFallbackVisitor(Visitor visitor) { 52 fallbackVisitor = visitor; 53 } 54 55 /** 56 * Sets {@code visitor} as the visitor for all string instructions. 57 */ 58 public void setStringVisitor(Visitor visitor) { 59 stringVisitor = visitor; 60 } 61 62 /** 63 * Sets {@code visitor} as the visitor for all type instructions. 64 */ 65 public void setTypeVisitor(Visitor visitor) { 66 typeVisitor = visitor; 67 } 68 69 /** 70 * Sets {@code visitor} as the visitor for all field instructions. 71 */ 72 public void setFieldVisitor(Visitor visitor) { 73 fieldVisitor = visitor; 74 } 75 76 /** 77 * Sets {@code visitor} as the visitor for all method instructions. 78 */ 79 public void setMethodVisitor(Visitor visitor) { 80 methodVisitor = visitor; 81 } 82 83 /** Sets {@code visitor} as the visitor for all method and proto instructions. */ 84 public void setMethodAndProtoVisitor(Visitor visitor) { 85 methodAndProtoVisitor = visitor; 86 } 87 88 /** Sets {@code visitor} as the visitor for all call site instructions. */ 89 public void setCallSiteVisitor(Visitor visitor) { 90 callSiteVisitor = visitor; 91 } 92 93 public void visitAll(DecodedInstruction[] decodedInstructions) 94 throws DexException { 95 int size = decodedInstructions.length; 96 97 for (int i = 0; i < size; i++) { 98 DecodedInstruction one = decodedInstructions[i]; 99 if (one == null) { 100 continue; 101 } 102 103 callVisit(decodedInstructions, one); 104 } 105 } 106 107 public void visitAll(short[] encodedInstructions) throws DexException { 108 DecodedInstruction[] decodedInstructions = 109 DecodedInstruction.decodeAll(encodedInstructions); 110 visitAll(decodedInstructions); 111 } 112 113 private void callVisit(DecodedInstruction[] all, DecodedInstruction one) { 114 Visitor visitor = null; 115 116 switch (OpcodeInfo.getIndexType(one.getOpcode())) { 117 case STRING_REF: visitor = stringVisitor; break; 118 case TYPE_REF: visitor = typeVisitor; break; 119 case FIELD_REF: visitor = fieldVisitor; break; 120 case METHOD_REF: visitor = methodVisitor; break; 121 case METHOD_AND_PROTO_REF: visitor = methodAndProtoVisitor; break; 122 case CALL_SITE_REF: visitor = callSiteVisitor; break; 123 } 124 125 if (visitor == null) { 126 visitor = fallbackVisitor; 127 } 128 129 if (visitor != null) { 130 visitor.visit(all, one); 131 } 132 } 133 134 public interface Visitor { 135 void visit(DecodedInstruction[] all, DecodedInstruction one); 136 } 137} 138