CodeReader.java revision 579d7739c53a2707ad711a2d2cae46d7d782f061
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.dx.io.instructions.DecodedInstruction;
20import com.android.dx.util.DexException;
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
32    /**
33     * Sets {@code visitor} as the visitor for all instructions.
34     */
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     */
47    public void setFallbackVisitor(Visitor visitor) {
48        fallbackVisitor = visitor;
49    }
50
51    /**
52     * Sets {@code visitor} as the visitor for all string instructions.
53     */
54    public void setStringVisitor(Visitor visitor) {
55        stringVisitor = visitor;
56    }
57
58    /**
59     * Sets {@code visitor} as the visitor for all type instructions.
60     */
61    public void setTypeVisitor(Visitor visitor) {
62        typeVisitor = visitor;
63    }
64
65    /**
66     * Sets {@code visitor} as the visitor for all field instructions.
67     */
68    public void setFieldVisitor(Visitor visitor) {
69        fieldVisitor = visitor;
70    }
71
72    /**
73     * Sets {@code visitor} as the visitor for all method instructions.
74     */
75    public void setMethodVisitor(Visitor visitor) {
76        methodVisitor = visitor;
77    }
78
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
93    public void visitAll(short[] encodedInstructions) throws DexException {
94        DecodedInstruction[] decodedInstructions =
95            DecodedInstruction.decodeAll(encodedInstructions);
96        visitAll(decodedInstructions);
97    }
98
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 {
119        void visit(DecodedInstruction[] all, DecodedInstruction one);
120    }
121}
122