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