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 
17 package com.android.dx.io;
18 
19 import com.android.dex.DexException;
20 import com.android.dx.io.instructions.DecodedInstruction;
21 
22 /**
23  * Walks through a block of code and calls visitor call backs.
24  */
25 public 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 
32     /**
33      * Sets {@code visitor} as the visitor for all instructions.
34      */
setAllVisitors(Visitor visitor)35     public void setAllVisitors(Visitor visitor) {
36         fallbackVisitor = visitor;
37         stringVisitor = visitor;
38         typeVisitor = visitor;
39         fieldVisitor = visitor;
40         methodVisitor = visitor;
41     }
42 
43     /**
44      * Sets {@code visitor} as the visitor for all instructions not
45      * otherwise handled.
46      */
setFallbackVisitor(Visitor visitor)47     public void setFallbackVisitor(Visitor visitor) {
48         fallbackVisitor = visitor;
49     }
50 
51     /**
52      * Sets {@code visitor} as the visitor for all string instructions.
53      */
setStringVisitor(Visitor visitor)54     public void setStringVisitor(Visitor visitor) {
55         stringVisitor = visitor;
56     }
57 
58     /**
59      * Sets {@code visitor} as the visitor for all type instructions.
60      */
setTypeVisitor(Visitor visitor)61     public void setTypeVisitor(Visitor visitor) {
62         typeVisitor = visitor;
63     }
64 
65     /**
66      * Sets {@code visitor} as the visitor for all field instructions.
67      */
setFieldVisitor(Visitor visitor)68     public void setFieldVisitor(Visitor visitor) {
69         fieldVisitor = visitor;
70     }
71 
72     /**
73      * Sets {@code visitor} as the visitor for all method instructions.
74      */
setMethodVisitor(Visitor visitor)75     public void setMethodVisitor(Visitor visitor) {
76         methodVisitor = visitor;
77     }
78 
visitAll(DecodedInstruction[] decodedInstructions)79     public void visitAll(DecodedInstruction[] decodedInstructions)
80             throws DexException {
81         int size = decodedInstructions.length;
82 
83         for (int i = 0; i < size; i++) {
84             DecodedInstruction one = decodedInstructions[i];
85             if (one == null) {
86                 continue;
87             }
88 
89             callVisit(decodedInstructions, one);
90         }
91     }
92 
visitAll(short[] encodedInstructions)93     public void visitAll(short[] encodedInstructions) throws DexException {
94         DecodedInstruction[] decodedInstructions =
95             DecodedInstruction.decodeAll(encodedInstructions);
96         visitAll(decodedInstructions);
97     }
98 
callVisit(DecodedInstruction[] all, DecodedInstruction one)99     private void callVisit(DecodedInstruction[] all, DecodedInstruction one) {
100         Visitor visitor = null;
101 
102         switch (OpcodeInfo.getIndexType(one.getOpcode())) {
103             case STRING_REF: visitor = stringVisitor; break;
104             case TYPE_REF:   visitor = typeVisitor;   break;
105             case FIELD_REF:  visitor = fieldVisitor;  break;
106             case METHOD_REF: visitor = methodVisitor; break;
107         }
108 
109         if (visitor == null) {
110             visitor = fallbackVisitor;
111         }
112 
113         if (visitor != null) {
114             visitor.visit(all, one);
115         }
116     }
117 
118     public interface Visitor {
visit(DecodedInstruction[] all, DecodedInstruction one)119         void visit(DecodedInstruction[] all, DecodedInstruction one);
120     }
121 }
122