Home | History | Annotate | Download | only in io
      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     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