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;
31e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson
32e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson    /**
3338b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein     * Sets {@code visitor} as the visitor for all instructions.
3438b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein     */
3538b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein    public void setAllVisitors(Visitor visitor) {
36f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein        fallbackVisitor = visitor;
37f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein        stringVisitor = visitor;
38f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein        typeVisitor = visitor;
39f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein        fieldVisitor = visitor;
40f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein        methodVisitor = visitor;
41f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein    }
42f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein
43f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein    /**
44f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein     * Sets {@code visitor} as the visitor for all instructions not
45f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein     * otherwise handled.
46f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein     */
47f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein    public void setFallbackVisitor(Visitor visitor) {
48f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein        fallbackVisitor = visitor;
4938b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein    }
5038b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein
5138b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein    /**
52e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson     * Sets {@code visitor} as the visitor for all string instructions.
53e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson     */
54e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson    public void setStringVisitor(Visitor visitor) {
55f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein        stringVisitor = visitor;
56e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson    }
57e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson
58e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson    /**
59e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson     * Sets {@code visitor} as the visitor for all type instructions.
60e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson     */
61e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson    public void setTypeVisitor(Visitor visitor) {
62f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein        typeVisitor = visitor;
63e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson    }
64e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson
65e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson    /**
66e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson     * Sets {@code visitor} as the visitor for all field instructions.
67e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson     */
68e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson    public void setFieldVisitor(Visitor visitor) {
69f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein        fieldVisitor = visitor;
70e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson    }
71e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson
72e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson    /**
73e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson     * Sets {@code visitor} as the visitor for all method instructions.
74e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson     */
75e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson    public void setMethodVisitor(Visitor visitor) {
76f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein        methodVisitor = visitor;
77e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson    }
78e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson
7938b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein    public void visitAll(DecodedInstruction[] decodedInstructions)
8038b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein            throws DexException {
8138b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein        int size = decodedInstructions.length;
82e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson
8338b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein        for (int i = 0; i < size; i++) {
84f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein            DecodedInstruction one = decodedInstructions[i];
85f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein            if (one == null) {
86e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson                continue;
87e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson            }
88e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson
89f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein            callVisit(decodedInstructions, one);
90e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson        }
91e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson    }
92e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson
9338b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein    public void visitAll(short[] encodedInstructions) throws DexException {
9438b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein        DecodedInstruction[] decodedInstructions =
9538b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein            DecodedInstruction.decodeAll(encodedInstructions);
9638b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein        visitAll(decodedInstructions);
9738b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein    }
9838b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein
99f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein    private void callVisit(DecodedInstruction[] all, DecodedInstruction one) {
100f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein        Visitor visitor = null;
101e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson
102f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein        switch (OpcodeInfo.getIndexType(one.getOpcode())) {
103f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein            case STRING_REF: visitor = stringVisitor; break;
104f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein            case TYPE_REF:   visitor = typeVisitor;   break;
105f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein            case FIELD_REF:  visitor = fieldVisitor;  break;
106f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein            case METHOD_REF: visitor = methodVisitor; break;
107e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson        }
108e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson
109f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein        if (visitor == null) {
110f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein            visitor = fallbackVisitor;
111e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson        }
112e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson
113f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein        if (visitor != null) {
114f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein            visitor.visit(all, one);
115e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson        }
116e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson    }
117e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson
118e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson    public interface Visitor {
119a754fbb1555f9ac2d14de0ffd0046c780732da5aDan Bornstein        void visit(DecodedInstruction[] all, DecodedInstruction one);
120e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson    }
121e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson}
122